summaryrefslogtreecommitdiff
path: root/eaaf_modules
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_modules')
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/pom.xml115
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java221
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java135
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java14
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java64
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java16
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java20
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java24
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java16
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java17
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java17
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java16
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java16
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java241
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java227
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java211
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java321
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java87
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java98
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java224
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java800
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java482
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java85
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java640
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java368
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java677
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java389
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java166
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/pom.xml2
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java160
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICmsSignatureVerificationResponse.java (renamed from eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICMSSignatureVerificationResponse.java)2
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java115
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java17
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java37
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java39
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java14
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java11
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java26
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java14
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java14
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java11
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java26
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java14
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java124
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java27
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java198
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java28
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java34
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java601
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java258
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java9
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java10
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java93
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java115
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java180
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java193
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider2
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml40
-rw-r--r--eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java109
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/pom.xml189
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java54
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java139
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java36
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java48
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java178
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java29
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java50
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java109
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java63
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java119
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java42
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java58
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java243
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java35
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java61
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java42
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java22
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java238
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java29
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java59
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java154
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java151
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java51
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java55
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java35
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java28
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java64
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java58
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java65
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java40
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java30
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java46
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java41
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java66
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java41
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2Exception.java50
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java34
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotAllowedException.java44
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java44
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java32
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java33
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java48
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java28
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java30
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java53
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java72
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java83
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java219
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java449
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java418
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java325
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java249
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java221
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java450
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java242
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java436
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java169
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java36
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java45
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java45
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java76
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java75
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java45
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java31
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java45
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java32
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java42
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java41
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java75
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java75
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java41
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java26
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java42
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java16
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java260
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java69
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java61
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java73
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java60
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java960
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java80
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java115
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java278
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java236
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java79
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java97
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java122
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java122
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java125
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java86
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java107
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java94
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java156
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java177
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java158
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java133
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java61
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java141
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java58
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java535
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java104
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java109
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SAML2Utils.java201
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java493
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java33
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java60
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java53
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java113
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java275
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java236
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java252
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java172
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java146
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java195
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java64
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java107
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java75
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java66
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java84
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java71
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java207
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java516
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider2
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties31
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java328
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java613
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/PvpCoreMessageSourceTest.java43
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java147
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java474
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java70
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java764
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java854
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java216
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java93
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java80
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java167
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java301
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java742
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props19
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml81
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml38
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml11
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.xml11
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b641
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml81
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml52
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml52
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt10
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml54
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/hsm_facade_trust_root.crt10
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jksbin0 -> 3980 bytes
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jksbin0 -> 2733 bytes
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12bin0 -> 3204 bytes
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml126
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml242
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml135
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml43
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml107
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml107
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml122
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml162
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html3
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml21
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml21
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml20
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml25
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/pom.xml56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java54
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java48
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java62
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java76
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java55
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java58
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java70
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java50
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java46
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java40
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java35
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java59
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java549
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java299
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java203
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java69
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java62
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java328
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java459
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java469
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider2
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml35
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java226
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java156
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java67
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java56
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java25
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java52
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java16
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java18
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props12
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml46
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml11
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jksbin0 -> 2733 bytes
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml126
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml31
-rw-r--r--eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml48
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/pom.xml43
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java48
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java195
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java188
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java80
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java68
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java68
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java71
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java259
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java265
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java16
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java673
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider1
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml19
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties17
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java57
-rw-r--r--eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java39
-rw-r--r--eaaf_modules/pom.xml2
298 files changed, 23592 insertions, 13150 deletions
diff --git a/eaaf_modules/eaaf_module_auth_sl20/pom.xml b/eaaf_modules/eaaf_module_auth_sl20/pom.xml
index d3c141d3..81611aff 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/pom.xml
+++ b/eaaf_modules/eaaf_module_auth_sl20/pom.xml
@@ -1,14 +1,17 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.gv.egiz.eaaf</groupId>
<artifactId>eaaf_modules</artifactId>
- <version>1.0.13.2</version>
+ <version>1.1.0</version>
</parent>
<artifactId>eaaf_module_auth_sl20</artifactId>
<name>Generic SL2.0 authentication</name>
-
- <licenses>
+
+ <licenses>
<license>
<name>European Union Public License, version 1.2 (EUPL-1.2)</name>
<url>https://opensource.org/licenses/EUPL-1.2</url>
@@ -24,37 +27,37 @@
<organizationUrl>https://www.egiz.gv.at</organizationUrl>
</developer>
</developers>
-
+
<dependencies>
- <dependency>
- <groupId>at.gv.egiz.eaaf</groupId>
- <artifactId>eaaf-core</artifactId>
- <version>${egiz.eaaf.version}</version>
- </dependency>
- <dependency>
- <groupId>org.bitbucket.b_c</groupId>
- <artifactId>jose4j</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </dependency>
-
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <scope>provided</scope>
- </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ <version>${egiz.eaaf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.bitbucket.b_c</groupId>
+ <artifactId>jose4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
-
+
<build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- </resource>
- </resources>
-
- <plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@@ -70,13 +73,13 @@
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<configuration>
- <archive>
- <manifest>
- <addClasspath>true</addClasspath>
- <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
- <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
- </manifest>
- </archive>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+ </manifest>
+ </archive>
</configuration>
</plugin>
@@ -92,23 +95,23 @@
</filesets>
</configuration>
</plugin>
-
+
<!-- enable co-existence of testng and junit -->
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>${surefire.version}</version>
- <configuration>
- <threadCount>1</threadCount>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>org.apache.maven.surefire</groupId>
- <artifactId>surefire-junit47</artifactId>
- <version>${surefire.version}</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
</build>
-
+
</project> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java
index 7e306f25..e9932ae8 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java
@@ -12,119 +12,130 @@ import org.springframework.beans.factory.annotation.Autowired;
import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule;
import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager;
import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;
-
/**
+ * AuthModule to select a Securtiy-Layer 2.0 based authentication process.
+ *
* @author tlenz
*
*/
-public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule {
- private static final Logger log = LoggerFactory.getLogger(AbstractSL20AuthenticationModulImpl.class);
-
- private int priority = 3;
- public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4");
-
- @Autowired(required=true) protected IConfiguration authConfig;
- @Autowired(required=true) private AbstractAuthenticationManager authManager;
-
- @Override
- public int getPriority() {
- return priority;
- }
-
- /**
- * Sets the priority of this module. Default value is {@code 0}.
- * @param priority The priority.
- */
- public void setPriority(int priority) {
- this.priority = priority;
- }
-
- @PostConstruct
- protected void initalSL20Authentication() {
- //parameter to whiteList
- authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE);
- authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE);
-
- }
-
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext)
- */
- @Override
- public String selectProcess(ExecutionContext context, IRequest pendingReq) {
- final ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration();
-
- if (spConfig == null) {
- log.error("Suspect state. NO SP CONFIGURATION IN CONTEXT!");
- throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN CONTEXT!");
-
- }
-
- final String sl20ClientTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE.toLowerCase());
- final String sl20VDATypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase());
-
- if (authConfig.getBasicConfigurationBoolean(getGeneralConfigPropertyNameEnableModule(), getGeneralConfigPropertyNameEnableModuleDefault())) {
- if (spConfig != null &&
- StringUtils.isNotEmpty(spConfig.getConfigurationValue(getSPConfigPropertyNameEnableModule())) &&
- Boolean.valueOf(spConfig.getConfigurationValue(getSPConfigPropertyNameEnableModule()))) {
- log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier());
- log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + ": " + sl20ClientTypeHeader);
- log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE + ": " + sl20VDATypeHeader);
- return getProcessName();
-
- } else {
- log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier());
- return null;
-
- }
-
- } else {
- log.trace("SL2.0 is NOT enabled with property: {}", getGeneralConfigPropertyNameEnableModule());
- return null;
-
- }
-
- }
-
- /**
- * Get the general configuration-key that holds the enabled key for this authentication module
- *
- * @return
- */
- public abstract String getGeneralConfigPropertyNameEnableModule();
-
- /**
- * Get the default value of the general configuration-key that holds the enabled key for this authentication module
- *
- * @return
- */
- public abstract boolean getGeneralConfigPropertyNameEnableModuleDefault();
-
- /**
- * Get the SP specific configuration-key that holds the enabled key for this authentication module
- *
- * @return configuration key for SP configuration
- */
- public abstract String getSPConfigPropertyNameEnableModule();
-
- /**
- * Get the name of this specific SL2.0 process
- *
- * @return
- */
- public abstract String getProcessName();
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()
- */
- @Override
- public abstract String[] getProcessDefinitions();
+public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule {
+ private static final Logger log = LoggerFactory.getLogger(AbstractSL20AuthenticationModulImpl.class);
+
+ private int priority = 3;
+ public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4");
+
+ @Autowired(required = true)
+ protected IConfiguration authConfig;
+ @Autowired(required = true)
+ private AbstractAuthenticationManager authManager;
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Sets the priority of this module. Default value is {@code 0}.
+ *
+ * @param priority The priority.
+ */
+ public void setPriority(final int priority) {
+ this.priority = priority;
+ }
+
+ @PostConstruct
+ protected void initalSL20Authentication() {
+ // parameter to whiteList
+ authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE);
+ authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.
+ * egovernment.moa.id.process .api.ExecutionContext)
+ */
+ @Override
+ public String selectProcess(final ExecutionContext context, final IRequest pendingReq) {
+ final ISpConfiguration spConfig = pendingReq.getServiceProviderConfiguration();
+
+ if (spConfig == null) {
+ log.error("Suspect state. NO SP CONFIGURATION IN CONTEXT!");
+ throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN CONTEXT!");
+
+ }
+
+ final String sl20ClientTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE.toLowerCase());
+ final String sl20VdaTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase());
+
+ if (authConfig.getBasicConfigurationBoolean(getGeneralConfigPropertyNameEnableModule(),
+ getGeneralConfigPropertyNameEnableModuleDefault())) {
+ if (StringUtils.isNotEmpty(spConfig.getConfigurationValue(getSpConfigPropertyNameEnableModule()))
+ && Boolean.valueOf(spConfig.getConfigurationValue(getSpConfigPropertyNameEnableModule()))) {
+ log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier());
+ log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + ": " + sl20ClientTypeHeader);
+ log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE + ": " + sl20VdaTypeHeader);
+ return getProcessName();
+
+ } else {
+ log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier());
+ return null;
+
+ }
+
+ } else {
+ log.trace("SL2.0 is NOT enabled with property: {}", getGeneralConfigPropertyNameEnableModule());
+ return null;
+
+ }
+
+ }
+
+ /**
+ * Get the general configuration-key that holds the enabled key for this
+ * authentication module.
+ *
+ * @return
+ */
+ public abstract String getGeneralConfigPropertyNameEnableModule();
+
+ /**
+ * Get the default value of the general configuration-key that holds the enabled
+ * key for this authentication module.
+ *
+ * @return
+ */
+ public abstract boolean getGeneralConfigPropertyNameEnableModuleDefault();
+
+ /**
+ * Get the SP specific configuration-key that holds the enabled key for this
+ * authentication module.
+ *
+ * @return configuration key for SP configuration
+ */
+ public abstract String getSpConfigPropertyNameEnableModule();
+
+ /**
+ * Get the name of this specific SL2.0 process.
+ *
+ * @return
+ */
+ public abstract String getProcessName();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()
+ */
+ @Override
+ public abstract String[] getProcessDefinitions();
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java
index a1490d2b..11fd41fb 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java
@@ -1,58 +1,87 @@
package at.gv.egiz.eaaf.modules.auth.sl20;
public class Constants {
-
- public static final String CONFIG_PROP_PREFIX = "modules.sl20";
- public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID = CONFIG_PROP_PREFIX + ".vda.urls.qualeID.";
-
- public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX + ".vda.authblock.transformation.id";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = CONFIG_PROP_PREFIX + ".security.keystore.path";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = CONFIG_PROP_PREFIX + ".security.keystore.password";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = CONFIG_PROP_PREFIX + ".security.sign.alias";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = CONFIG_PROP_PREFIX + ".security.sign.password";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX + ".security.encryption.alias";;
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX + ".security.encryption.password";
-
- public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default";
- public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT;
- public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list";
- public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds.";
-
- public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX + ".security.eID.validation.disable";
- public static final String CONFIG_PROP_ENABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.enabled";
- public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.required";
- public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = CONFIG_PROP_PREFIX + ".security.eID.signed.result.required";
-
- public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".testing.ipc.return.url";
- public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = CONFIG_PROP_PREFIX + ".testing.redirect.http.code";
- public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "303";
-
- public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled";
- public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints";
-
- public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_";
-
- /**
- * Only dummy data for development!!!!!!
- */
- public static final String DUMMY_SIGNING_CERT =
- "MIIC9zCCAd8CBFretWcwDQYJKoZIhvcNAQEOBQAwQDELMAkGA1UEBhMCQVQxDTAL\n" +
- "BgNVBAoMBEVHSVoxIjAgBgNVBAMMGW93biBkdW1teSBtZXRhZGF0YSBzaWduZXIw\n" +
- "HhcNMTgwNDI0MDQ0MTExWhcNMjEwMTE3MDQ0MTExWjBAMQswCQYDVQQGEwJBVDEN\n" +
- "MAsGA1UECgwERUdJWjEiMCAGA1UEAwwZb3duIGR1bW15IG1ldGFkYXRhIHNpZ25l\n" +
- "cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW5trHH\n" +
- "Rb1s60QtGNp2v1nfMg1R6h7SzygtmO869v5bqrVBBVGmujslr7W8cZ2DLmJoQx1N\n" +
- "WwhccjXTHpNPw0B70qHGch2uRNkqkizSOlwth0Ll2DJtzxTolbajYdg+xppXScUq\n" +
- "WNlNZndauPSnB2CESgNkaUou4x4YVSDInugAtLvdLx8rf2YcuidI6UIXxeSZr3VO\n" +
- "Z12YtddzcJ+lwh7OX8B0UvLsdYjKjefjEudyuNBmVwLv4K2LsFhSqgE1CAzk3oCb\n" +
- "V2A84klaWVPiXoBiOucyouvX781WVp1aCBp0QA8gpJH7/2wRsdPQ90tjMzM7dcgY\n" +
- "LDkCAwEAATANBgkqhkiG9w0BAQ4FAAOCAQEAQuYRQcCNLDYU1ItliYz9f28+KDyU\n" +
- "8WjF3NDZrlJbGSKQ4n7wkBfxdK3zprmpHadWDB+aZaPt/+voE2FduzPiLUDlpazN\n" +
- "60JJ5/YHZ3q9MZvdoNg6rjkpioWatoj/smUkT6oUWL/gp8tH12fOd2oJygBqXMve\n" +
- "3y3qVCghnjRaMYuXcScTZcjH9yebkTLygirtw34oGVb7t+HwbtcN65fUIBly6Rcl\n" +
- "8NV3pwOKhXFKDAqXUpvhebL4+tWOqPdqfIfGaE6rELfTf3icGY3CQCzDz5Gp0Ptc\n" +
- "TfQqm64xnhtAruXNJXWg2ptg+GuQgWnJUgQ8wLNMxw9XdeEwlQo5dL6xmg==";
-
- public static final String DUMMY_SIGNING_CERT_FINGERPRINT = "IwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW";
+
+ public static final String CONFIG_PROP_PREFIX = "modules.sl20";
+ public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID = CONFIG_PROP_PREFIX + ".vda.urls.qualeID.";
+
+ public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX
+ + ".vda.authblock.transformation.id";
+
+ //KeyStore configuration
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE =
+ CONFIG_PROP_PREFIX + ".security.keystore.type";
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME =
+ CONFIG_PROP_PREFIX + ".security.keystore.name";
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH =
+ CONFIG_PROP_PREFIX + ".security.keystore.path";
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD =
+ CONFIG_PROP_PREFIX + ".security.keystore.password";
+
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS =
+ CONFIG_PROP_PREFIX + ".security.sign.alias";
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD =
+ CONFIG_PROP_PREFIX + ".security.sign.password";
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS =
+ CONFIG_PROP_PREFIX + ".security.encryption.alias";
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD =
+ CONFIG_PROP_PREFIX + ".security.encryption.password";
+
+ //TrustStore configuration
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE =
+ CONFIG_PROP_PREFIX + ".security.truststore.type";
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME =
+ CONFIG_PROP_PREFIX + ".security.truststore.name";
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH =
+ CONFIG_PROP_PREFIX + ".security.truststore.path";
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD =
+ CONFIG_PROP_PREFIX + ".security.truststore.password";
+
+
+ public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default";
+ public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID
+ + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT;
+ public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list";
+ public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds.";
+
+ public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX
+ + ".security.eID.validation.disable";
+ public static final String CONFIG_PROP_ENABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX
+ + ".security.eID.encryption.enabled";
+ public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = CONFIG_PROP_PREFIX
+ + ".security.eID.encryption.required";
+ public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = CONFIG_PROP_PREFIX
+ + ".security.eID.signed.result.required";
+
+ public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".testing.ipc.return.url";
+ public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = CONFIG_PROP_PREFIX + ".testing.redirect.http.code";
+ public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "303";
+
+ public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled";
+ public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints";
+
+ public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_";
+
+ /**
+ * Only dummy data for development!!!!!!.
+ */
+ public static final String DUMMY_SIGNING_CERT = "MIIC9zCCAd8CBFretWcwDQYJKoZIhvcNAQEOBQAwQDELMAkGA1UEBhMCQVQxDTAL\n"
+ + "BgNVBAoMBEVHSVoxIjAgBgNVBAMMGW93biBkdW1teSBtZXRhZGF0YSBzaWduZXIw\n"
+ + "HhcNMTgwNDI0MDQ0MTExWhcNMjEwMTE3MDQ0MTExWjBAMQswCQYDVQQGEwJBVDEN\n"
+ + "MAsGA1UECgwERUdJWjEiMCAGA1UEAwwZb3duIGR1bW15IG1ldGFkYXRhIHNpZ25l\n"
+ + "cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW5trHH\n"
+ + "Rb1s60QtGNp2v1nfMg1R6h7SzygtmO869v5bqrVBBVGmujslr7W8cZ2DLmJoQx1N\n"
+ + "WwhccjXTHpNPw0B70qHGch2uRNkqkizSOlwth0Ll2DJtzxTolbajYdg+xppXScUq\n"
+ + "WNlNZndauPSnB2CESgNkaUou4x4YVSDInugAtLvdLx8rf2YcuidI6UIXxeSZr3VO\n"
+ + "Z12YtddzcJ+lwh7OX8B0UvLsdYjKjefjEudyuNBmVwLv4K2LsFhSqgE1CAzk3oCb\n"
+ + "V2A84klaWVPiXoBiOucyouvX781WVp1aCBp0QA8gpJH7/2wRsdPQ90tjMzM7dcgY\n"
+ + "LDkCAwEAATANBgkqhkiG9w0BAQ4FAAOCAQEAQuYRQcCNLDYU1ItliYz9f28+KDyU\n"
+ + "8WjF3NDZrlJbGSKQ4n7wkBfxdK3zprmpHadWDB+aZaPt/+voE2FduzPiLUDlpazN\n"
+ + "60JJ5/YHZ3q9MZvdoNg6rjkpioWatoj/smUkT6oUWL/gp8tH12fOd2oJygBqXMve\n"
+ + "3y3qVCghnjRaMYuXcScTZcjH9yebkTLygirtw34oGVb7t+HwbtcN65fUIBly6Rcl\n"
+ + "8NV3pwOKhXFKDAqXUpvhebL4+tWOqPdqfIfGaE6rELfTf3icGY3CQCzDz5Gp0Ptc\n"
+ + "TfQqm64xnhtAruXNJXWg2ptg+GuQgWnJUgQ8wLNMxw9XdeEwlQo5dL6xmg==";
+
+ public static final String DUMMY_SIGNING_CERT_FINGERPRINT = "IwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW";
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java
index e19ef5fc..af155206 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java
@@ -1,16 +1,16 @@
package at.gv.egiz.eaaf.modules.auth.sl20;
/**
- * Set of event codes uses in Auth-Handler implementation
- *
+ * Set of event codes uses in Auth-Handler implementation.
+ *
* @author tlenz
*
*/
public class EventCodes {
- public static final int AUTHPROCESS_SL20_SELECTED = 4111;
- public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112;
- public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113;
-
- public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113;
+ public static final int AUTHPROCESS_SL20_SELECTED = 4111;
+ public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112;
+ public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113;
+
+ public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113;
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java
index 0c625a9b..bb0c41d7 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java
@@ -7,33 +7,39 @@ import com.fasterxml.jackson.databind.JsonNode;
public class VerificationResult {
- private Boolean validSigned = null;
- private List<X509Certificate> certs = null;
- private JsonNode payload = null;
-
- public VerificationResult(JsonNode payload) {
- this.payload = payload;
-
- }
-
- public VerificationResult(JsonNode string, List<X509Certificate> certs, boolean wasValidSigned) {
- this.payload = string;
- this.certs = certs;
- this.validSigned = wasValidSigned;
-
- }
-
- public Boolean isValidSigned() {
- return validSigned;
- }
- public List<X509Certificate> getCertChain() {
- return certs;
- }
- public JsonNode getPayload() {
- return payload;
- }
-
-
-
-
+ private Boolean validSigned = null;
+ private List<X509Certificate> certs = null;
+ private JsonNode payload = null;
+
+ public VerificationResult(final JsonNode payload) {
+ this.payload = payload;
+
+ }
+
+ /**
+ * JWS signature verification-result container.
+ *
+ * @param payload JWS payload
+ * @param certs JWS signercertificate
+ * @param wasValidSigned true if signature was valid
+ */
+ public VerificationResult(final JsonNode payload, final List<X509Certificate> certs, final boolean wasValidSigned) {
+ this.payload = payload;
+ this.certs = certs;
+ this.validSigned = wasValidSigned;
+
+ }
+
+ public Boolean isValidSigned() {
+ return validSigned;
+ }
+
+ public List<X509Certificate> getCertChain() {
+ return certs;
+ }
+
+ public JsonNode getPayload() {
+ return payload;
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java
new file mode 100644
index 00000000..a14fbe9e
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java
@@ -0,0 +1,16 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
+
+public class SL20EidDataValidationException extends SL20Exception {
+ private static final long serialVersionUID = 1L;
+
+ public SL20EidDataValidationException(final Object[] parameters) {
+ super("sl20.07", parameters);
+
+ }
+
+ public SL20EidDataValidationException(final Object[] parameters, final Throwable e) {
+ super("sl20.07", parameters, e);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java
index b23b5ca3..12921ad6 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java
@@ -1,19 +1,19 @@
package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
-import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
-public class SL20Exception extends EAAFAuthenticationException {
+public class SL20Exception extends EaafAuthenticationException {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- public SL20Exception(String messageId, Object[] parameters) {
- super(messageId, parameters);
+ public SL20Exception(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
- }
-
- public SL20Exception(String messageId, Object[] parameters, Throwable wrapped) {
- super(messageId, parameters, wrapped);
+ }
- }
+ public SL20Exception(final String messageId, final Object[] parameters, final Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java
index eaf55ba3..62abdeb8 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java
@@ -2,19 +2,19 @@ package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
public class SL20SecurityException extends SL20Exception {
- private static final long serialVersionUID = 3281385988027147449L;
+ private static final long serialVersionUID = 3281385988027147449L;
- public SL20SecurityException(Object[] parameters) {
- super("sl20.05", parameters);
- }
-
- public SL20SecurityException(String parameter) {
- super("sl20.05", new Object[] {parameter});
- }
-
- public SL20SecurityException(Object[] parameters, Throwable wrapped) {
- super("sl20.05", parameters, wrapped);
+ public SL20SecurityException(final Object[] parameters) {
+ super("sl20.05", parameters);
+ }
- }
+ public SL20SecurityException(final String parameter) {
+ super("sl20.05", new Object[] { parameter });
+ }
+
+ public SL20SecurityException(final Object[] parameters, final Throwable wrapped) {
+ super("sl20.05", parameters, wrapped);
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java
deleted file mode 100644
index 24df735a..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
-
-public class SL20eIDDataValidationException extends SL20Exception {
- private static final long serialVersionUID = 1L;
-
- public SL20eIDDataValidationException(Object[] parameters) {
- super("sl20.07", parameters);
-
- }
-
- public SL20eIDDataValidationException(Object[] parameters, Throwable e) {
- super("sl20.07", parameters, e);
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java
deleted file mode 100644
index 1f521ebc..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
-
-public class SLCommandoBuildException extends SL20Exception {
-
- private static final long serialVersionUID = 1L;
-
-
- public SLCommandoBuildException(String msg) {
- super("sl20.01", new Object[]{msg});
-
- }
-
- public SLCommandoBuildException(String msg, Throwable e) {
- super("sl20.01", new Object[]{msg}, e);
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java
deleted file mode 100644
index 60993e69..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
-
-public class SLCommandoParserException extends SL20Exception {
-
- private static final long serialVersionUID = 1L;
-
-
- public SLCommandoParserException(String msg) {
- super("sl20.02", new Object[]{msg});
-
- }
-
- public SLCommandoParserException(String msg, Throwable e) {
- super("sl20.02", new Object[]{msg}, e);
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java
new file mode 100644
index 00000000..361f57b7
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java
@@ -0,0 +1,16 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
+
+public class SlCommandoBuildException extends SL20Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public SlCommandoBuildException(final String msg) {
+ super("sl20.01", new Object[] { msg });
+
+ }
+
+ public SlCommandoBuildException(final String msg, final Throwable e) {
+ super("sl20.01", new Object[] { msg }, e);
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java
new file mode 100644
index 00000000..4993796a
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java
@@ -0,0 +1,16 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
+
+public class SlCommandoParserException extends SL20Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public SlCommandoParserException(final String msg) {
+ super("sl20.02", new Object[] { msg });
+
+ }
+
+ public SlCommandoParserException(final String msg, final Throwable e) {
+ super("sl20.02", new Object[] { msg }, e);
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java
new file mode 100644
index 00000000..d1887d5c
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java
@@ -0,0 +1,241 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.tasks;
+
+import java.security.cert.CertificateEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.jose4j.base64url.Base64Url;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;
+import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes;
+import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils;
+
+public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServletTask {
+ private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualEidRequestTask.class);
+
+ @Autowired(required = true)
+ private IHttpClientFactory httpClientFactory;
+ @Autowired(required = true)
+ protected IConfigurationWithSP authConfigWithSp;
+
+ @Override
+ public void execute(final ExecutionContext executionContext, final HttpServletRequest request,
+ final HttpServletResponse response) throws TaskExecutionException {
+
+ log.debug("Starting SL2.0 authentication process .... ");
+
+ revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth");
+
+ try {
+ // get service-provider configuration
+ final ISpConfiguration oaConfig = pendingReq.getServiceProviderConfiguration();
+
+ if (oaConfig == null) {
+ log.warn("No SP configuration in pendingReq!");
+ throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN PendingRequest!");
+
+ }
+
+ // get basic configuration parameters
+ final String vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext);
+ if (StringUtils.isEmpty(vdaQualEidDUrl)) {
+ log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")");
+ throw new SL20Exception("sl20.03", new Object[] { "NO VDA URL for qualified eID" });
+
+ }
+
+ log.debug("Use {} as VDA end-point", vdaQualEidDUrl);
+ pendingReq.setRawDataToTransaction(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, vdaQualEidDUrl);
+ revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualEidDUrl);
+
+ // create SL2.0 command for qualified eID
+ final String signedQualEidCommand = buildSignedQualifiedEidCommand();
+
+ // build request container
+ final String qualEidReqId = Random.nextProcessReferenceValue();
+ final ObjectNode sl20Req = SL20JsonBuilderUtils.createGenericRequest(qualEidReqId, null, null,
+ signedQualEidCommand);
+
+ // build http POST request
+ final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualEidDUrl).build());
+ final List<NameValuePair> parameters = new ArrayList<>();
+ parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM,
+ Base64Url.encode(sl20Req.toString().getBytes("UTF-8"))));
+ httpReq.setEntity(new UrlEncodedFormEntity(parameters));
+
+ // build http GET request
+ // URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl);
+ // sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM,
+ // Base64Url.encode(sl20Req.toString().getBytes()));
+ // HttpGet httpReq = new HttpGet(sl20ReqUri.build());
+
+ // set native client header
+ httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE);
+
+ log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes("UTF-8")));
+
+ // request VDA
+ final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq);
+
+ // parse response
+ log.info("Receive response from VDA ... ");
+ final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp);
+ final VerificationResult respPayloadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false);
+
+ if (respPayloadContainer.isValidSigned() == null) {
+ log.debug("Receive unsigned payLoad from VDA");
+
+ }
+
+ final JsonNode respPayload = respPayloadContainer.getPayload();
+ if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()
+ .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) {
+ log.debug("Find 'redirect' command in VDA response ... ");
+ final JsonNode params = SL20JsonExtractorUtils.getJsonObjectValue(respPayload,
+ SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true);
+ final String redirectUrl = SL20JsonExtractorUtils.getStringValue(params,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true);
+ final JsonNode command = SL20JsonExtractorUtils.getJsonObjectValue(params,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false);
+ final String signedCommand = SL20JsonExtractorUtils.getStringValue(params,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false);
+
+ // create forward SL2.0 command
+ final ObjectNode sl20Forward = sl20Resp.deepCopy();
+ SL20JsonBuilderUtils.addOnlyOnceOfTwo(sl20Forward, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,
+ command.deepCopy(), signedCommand);
+
+ // store pending request
+ pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID,
+ qualEidReqId);
+ requestStoreage.storePendingRequest(pendingReq);
+
+ // forward SL2.0 command
+ // TODO: maybe add SL2ClientType Header from execution context
+ SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectUrl,
+ Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,
+ Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));
+
+ } else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()
+ .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {
+ JsonNode result = SL20JsonExtractorUtils.getJsonObjectValue(respPayload,
+ SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false);
+ if (result == null) {
+ result = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS,
+ false);
+ }
+
+ final String errorCode = SL20JsonExtractorUtils.getStringValue(result,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true);
+ final String errorMsg = SL20JsonExtractorUtils.getStringValue(result,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true);
+
+ log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg);
+ throw new SL20Exception("sl20.08", new Object[] { errorCode, errorMsg });
+
+ } else {
+ // TODO: update to add error handling
+ log.warn(
+ "Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText());
+ throw new SlCommandoParserException("Received an unrecognized command: "
+ + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).toString());
+ }
+
+ } catch (final EaafAuthenticationException e) {
+ throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e);
+
+ } catch (final Exception e) {
+ log.warn("SL2.0 Authentication FAILED with a generic error.", e);
+ throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+
+ } finally {
+ TransactionIdUtils.removeTransactionId();
+ TransactionIdUtils.removeSessionId();
+
+ }
+
+ }
+
+ /**
+ * Create a implementation specific qualified eID SL2.0 command
+ *
+ * @param oaConfig
+ *
+ * @return signed JWT token as serialized {@link String}
+ * @throws CertificateEncodingException In case of certificate parsing error
+ * @throws SL20Exception In case of a SL2.0 error
+ */
+ protected abstract String buildSignedQualifiedEidCommand() throws CertificateEncodingException, SL20Exception;
+
+ private String extractVdaUrlForSpecificOa(final ISpConfiguration oaConfig, final ExecutionContext executionContext) {
+
+ // load SP specific config for development and testing purposes
+ final String spSpecificVdaEndpoints = oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST);
+
+ // load general configuration
+ final Map<String, String> endPointMap = authConfigWithSp
+ .getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST);
+ endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT,
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT));
+ if (StringUtils.isNotEmpty(spSpecificVdaEndpoints)) {
+ endPointMap.putAll(KeyValueUtils.convertListToMap(
+ KeyValueUtils.getListOfCsvValues(KeyValueUtils.normalizeCsvValueString(spSpecificVdaEndpoints))));
+ log.debug("Find OA specific SL2.0 endpoints. Updating endPoint list ... ");
+
+ }
+
+ log.trace("Find #" + endPointMap.size() + " SL2.0 endpoints ... ");
+
+ // selection based on request Header
+ final String sl20VdaTypeHeader = (String) executionContext
+ .get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase());
+ if (StringUtils.isNotEmpty(sl20VdaTypeHeader)) {
+ final String vdaUrl = endPointMap.get(sl20VdaTypeHeader);
+ if (StringUtils.isNotEmpty(vdaUrl)) {
+ return vdaUrl.trim();
+ } else {
+ log.info("Can NOT find VDA with Id: " + sl20VdaTypeHeader + ". Use default VDA");
+ }
+
+ }
+
+ log.info("NO specific VDA endpoint requested or found. Use default VDA");
+ return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java
deleted file mode 100644
index 85302d83..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.tasks;
-
-import java.security.cert.CertificateEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.message.BasicNameValuePair;
-import org.jose4j.base64url.Base64Url;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
-import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
-import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
-import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException;
-import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
-import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
-import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory;
-import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
-import at.gv.egiz.eaaf.core.impl.utils.Random;
-import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils;
-import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes;
-import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONBuilderUtils;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONExtractorUtils;
-
-public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServletTask {
- private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualeIDRequestTask.class);
-
- @Autowired(required=true) private IHttpClientFactory httpClientFactory;
- @Autowired(required=true) protected IConfigurationWithSP authConfigWithSp;
-
- @Override
- public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
- throws TaskExecutionException {
-
- log.debug("Starting SL2.0 authentication process .... ");
-
- revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth");
-
- try {
- //get service-provider configuration
- final ISPConfiguration oaConfig = pendingReq.getServiceProviderConfiguration();
-
- if (oaConfig == null) {
- log.warn("No SP configuration in pendingReq!");
- throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN PendingRequest!");
-
- }
-
- //get basic configuration parameters
- final String vdaQualeIDUrl = extractVDAURLForSpecificOA(oaConfig, executionContext);
- if (StringUtils.isEmpty(vdaQualeIDUrl)) {
- log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")");
- throw new SL20Exception("sl20.03", new Object[]{"NO VDA URL for qualified eID"});
-
- }
-
- log.debug("Use {} as VDA end-point", vdaQualeIDUrl) ;
- pendingReq.setRawDataToTransaction(
- Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,
- vdaQualeIDUrl);
- revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualeIDUrl);
-
- //create SL2.0 command for qualified eID
- final String signedQualeIDCommand = buildSignedQualifiedEIDCommand();
-
- //build request container
- final String qualeIDReqId = Random.nextProcessReferenceValue();
- final ObjectNode sl20Req = SL20JSONBuilderUtils.createGenericRequest(qualeIDReqId, null, null, signedQualeIDCommand);
-
- //build http POST request
- final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualeIDUrl).build());
- final List<NameValuePair> parameters = new ArrayList<NameValuePair>();;
- parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes())));
- httpReq.setEntity(new UrlEncodedFormEntity(parameters ));
-
- //build http GET request
-// URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl);
-// sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes()));
-// HttpGet httpReq = new HttpGet(sl20ReqUri.build());
-
- //set native client header
- httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE);
-
- log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes()));
-
- //request VDA
- final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq);
-
- //parse response
- log.info("Receive response from VDA ... ");
- final JsonNode sl20Resp = SL20JSONExtractorUtils.getSL20ContainerFromResponse(httpResp);
- final VerificationResult respPayloadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20Resp, null, false);
-
- if (respPayloadContainer.isValidSigned() == null) {
- log.debug("Receive unsigned payLoad from VDA");
-
- }
-
- final JsonNode respPayload = respPayloadContainer.getPayload();
- if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()
- .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) {
- log.debug("Find 'redirect' command in VDA response ... ");
- final JsonNode params = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true);
- final String redirectURL = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true);
- final JsonNode command = SL20JSONExtractorUtils.getJSONObjectValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false);
- final String signedCommand = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false);
-
- //create forward SL2.0 command
- final ObjectNode sl20Forward = sl20Resp.deepCopy();
- SL20JSONBuilderUtils.addOnlyOnceOfTwo(sl20Forward,
- SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,
- command.deepCopy(), signedCommand);
-
- //store pending request
- pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID,
- qualeIDReqId);
- requestStoreage.storePendingRequest(pendingReq);
-
- //forward SL2.0 command
- //TODO: maybe add SL2ClientType Header from execution context
- SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL,
- Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));
-
- } else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()
- .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {
- JsonNode result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false);
- if (result == null)
- result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, false);
-
- final String errorCode = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true);
- final String errorMsg = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true);
-
- log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg);
- throw new SL20Exception("sl20.08", new Object[]{errorCode, errorMsg});
-
- } else {
- //TODO: update to add error handling
- log.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText());
- throw new SLCommandoParserException("Received an unrecognized command: \" + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()");
- }
-
-
- } catch (final EAAFAuthenticationException e) {
- throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e);
-
- } catch (final Exception e) {
- log.warn("SL2.0 Authentication FAILED with a generic error.", e);
- throw new TaskExecutionException(pendingReq, e.getMessage(), e);
-
- } finally {
- TransactionIDUtils.removeTransactionId();
- TransactionIDUtils.removeSessionId();
-
- }
-
- }
-
- /**
- * Create a implementation specific qualified eID SL2.0 command
- * @param oaConfig
- *
- * @return signed JWT token as serialized {@link String}
- * @throws CertificateEncodingException
- * @throws SLCommandoBuildException
- * @throws SL20Exception
- */
- protected abstract String buildSignedQualifiedEIDCommand() throws CertificateEncodingException, SL20Exception;
-
-
- private String extractVDAURLForSpecificOA(ISPConfiguration oaConfig, ExecutionContext executionContext) {
-
- //load SP specific config for development and testing purposes
- final String spSpecificVDAEndpoints = oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST);
-
- //load general configuration
- final Map<String, String> endPointMap = authConfigWithSp.getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST);
- endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT, authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT));
- if (StringUtils.isNotEmpty(spSpecificVDAEndpoints)) {
- endPointMap.putAll(KeyValueUtils.convertListToMap(
- KeyValueUtils.getListOfCSVValues(
- KeyValueUtils.normalizeCSVValueString(spSpecificVDAEndpoints))));
- log.debug("Find OA specific SL2.0 endpoints. Updating endPoint list ... ");
-
- }
-
- log.trace("Find #" + endPointMap.size() + " SL2.0 endpoints ... ");
-
- //selection based on request Header
- final String sl20VDATypeHeader = (String) executionContext.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase());
- if (StringUtils.isNotEmpty(sl20VDATypeHeader)) {
- final String vdaURL = endPointMap.get(sl20VDATypeHeader);
- if (StringUtils.isNotEmpty(vdaURL))
- return vdaURL.trim();
- else
- log.info("Can NOT find VDA with Id: " + sl20VDATypeHeader + ". Use default VDA");
-
- }
-
-
- log.info("NO specific VDA endpoint requested or found. Use default VDA");
- return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT);
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java
new file mode 100644
index 00000000..655cc2c6
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java
@@ -0,0 +1,211 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.tasks;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder;
+import at.gv.egiz.eaaf.core.impl.utils.StreamUtils;
+import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;
+import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes;
+import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJoseTools;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils;
+import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20ResponseUtils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jose4j.base64url.Base64Url;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonNode;
+
+public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask {
+ private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class);
+
+ @Autowired(required = true)
+ private IJoseTools joseTools;
+
+ @Override
+ public void execute(final ExecutionContext executionContext, final HttpServletRequest request,
+ final HttpServletResponse response) throws TaskExecutionException {
+ String sl20Result = null;
+
+ try {
+ log.debug("Receiving SL2.0 response process .... ");
+ JsonNode sl20ReqObj = null;
+
+ // A-Trust does not SET http-header 'SL2ClientType' with value 'native'
+ // If A-trust sends an error, its maybe FrontChannel on DataURL
+ // boolean aTrustErrorWorkAround = false;
+
+ try {
+ // get SL2.0 command or result from HTTP request
+ final Map<String, String> reqParams = getParameters(request);
+ sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM);
+
+ if (StringUtils.isEmpty(sl20Result)) {
+ // Workaround for SIC Handy-Signature, because it sends result in InputStream
+ final String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8");
+ if (StringUtils.isNotEmpty(isReqInput)) {
+ log.info("Use SIC Handy-Signature work-around!");
+ sl20Result = isReqInput.substring("slcommand=".length());
+
+ } else {
+ log.info("NO SL2.0 commando or result FOUND.");
+ throw new SL20Exception("sl20.04", null);
+ }
+
+ }
+
+ log.trace("Received SL2.0 result: " + sl20Result);
+ revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_DATAURL_IP, request.getRemoteAddr());
+
+ // parse SL2.0 command/result into JSON
+ try {
+ sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result));
+
+ } catch (final JsonParseException e) {
+ log.warn("SL2.0 command or result is NOT valid JSON.", e);
+ log.debug("SL2.0 msg: " + sl20Result);
+ throw new SL20Exception("sl20.02", new Object[] { "SL2.0 command or result is NOT valid JSON." }, e);
+
+ }
+
+ // check on errorMessage
+ final VerificationResult payLoadContainerErrorCheck = SL20JsonExtractorUtils.extractSL20PayLoad(sl20ReqObj,
+ joseTools, false);
+ if (SL20JsonExtractorUtils
+ .getStringValue(payLoadContainerErrorCheck.getPayload(), SL20Constants.SL20_COMMAND_CONTAINER_NAME, true)
+ .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {
+ log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... ");
+ final JsonNode errorResult = SL20JsonExtractorUtils.extractSL20Result(payLoadContainerErrorCheck.getPayload(),
+ joseTools, false);
+ final String errorCode = SL20JsonExtractorUtils.getStringValue(errorResult,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true);
+ final String errorMsg = SL20JsonExtractorUtils.getStringValue(errorResult,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false);
+
+ log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... ", errorCode, errorMsg);
+ // aTrustErrorWorkAround = true;
+ throw new SL20Exception("sl20.08", new Object[] { errorCode, errorMsg });
+
+ } else {
+ // Receive no error - To request validation
+
+ // validate reqId with inResponseTo
+ final String sl20ReqId = pendingReq
+ .getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class);
+ final String inRespTo = SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true);
+ if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) {
+ log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
+ throw new SL20SecurityException(
+ "SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
+ }
+
+ // validate signature
+ final VerificationResult payLoadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools,
+ authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true));
+
+ if (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned()) {
+ if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) {
+ log.info("SL20 result from VDA was not valid signed");
+ throw new SL20SecurityException(new Object[] { "Signature on SL20 result NOT valid." });
+
+ } else {
+ log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification "
+ + "is DISABLED by configuration!");
+
+ }
+ }
+
+ // extract payloaf
+ final JsonNode payLoad = payLoadContainer.getPayload();
+
+ // handle SL2.0 response payLoad
+ handleResponsePayLoad(payLoad);
+
+ }
+
+ } catch (final EaafAuthenticationException e) {
+ log.warn("SL2.0 processing error:", e);
+ if (sl20Result != null) {
+ log.debug("Received SL2.0 result: " + sl20Result);
+ }
+ pendingReq.setRawDataToTransaction(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
+ new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e));
+
+ } catch (final Exception e) {
+ log.warn("ERROR:", e);
+ log.warn("SL2.0 Authentication FAILED with a generic error.", e);
+ if (sl20Result != null) {
+ log.debug("Received SL2.0 result: " + sl20Result);
+ }
+ pendingReq.setRawDataToTransaction(
+ Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
+ new TaskExecutionException(pendingReq, e.getMessage(), e));
+
+ } finally {
+ // store pending request
+ requestStoreage.storePendingRequest(pendingReq);
+
+ // write SL2.0 response
+ if (sl20ReqObj != null) {
+ final String resumeEndpoint = new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(),
+ getResumeEndPoint(), pendingReq.getPendingRequestId());
+ SL20ResponseUtils.buildResponse(request, response, pendingReq, resumeEndpoint,
+ SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false),
+ authConfig);
+
+ } else {
+ SL20ResponseUtils.buildErrorResponse(response, "2000", "General transport Binding error");
+ }
+
+ }
+
+ } catch (final Exception e) {
+ // write internal server errror 500 according to SL2.0 specification, chapter
+ // https transport
+ // binding
+ log.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e);
+ if (sl20Result != null) {
+ log.debug("Received SL2.0 result: " + sl20Result);
+ }
+ try {
+ response.sendError(500, "Internal Server Error.");
+
+ } catch (final IOException e1) {
+ log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e);
+
+ }
+
+ } finally {
+ TransactionIdUtils.removeTransactionId();
+ TransactionIdUtils.removeSessionId();
+
+ }
+ }
+
+ protected abstract void handleResponsePayLoad(JsonNode payLoad)
+ throws SlCommandoParserException, SL20Exception, EaafStorageException;
+
+ protected abstract String getResumeEndPoint();
+
+
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java
deleted file mode 100644
index b4039cf9..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java
+++ /dev/null
@@ -1,321 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.tasks;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.entity.ContentType;
-import org.jose4j.base64url.Base64Url;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
-import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
-import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException;
-import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException;
-import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
-import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
-import at.gv.egiz.eaaf.core.impl.utils.DataURLBuilder;
-import at.gv.egiz.eaaf.core.impl.utils.StreamUtils;
-import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils;
-import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes;
-import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJOSETools;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONBuilderUtils;
-import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONExtractorUtils;
-
-
-public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask {
- private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualeIDTask.class);
-
- @Autowired(required=true) private IJOSETools joseTools;
-
- @Override
- public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
- throws TaskExecutionException {
- String sl20Result = null;
-
- try {
- log.debug("Receiving SL2.0 response process .... ");
- JsonNode sl20ReqObj = null;
-
- //A-Trust does not SET http-header 'SL2ClientType' with value 'native'
- //If A-trust sends an error, its maybe FrontChannel on DataURL
- //boolean aTrustErrorWorkAround = false;
-
- try {
- //get SL2.0 command or result from HTTP request
- final Map<String, String> reqParams = getParameters(request);
- sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM);
-
- if (StringUtils.isEmpty(sl20Result)) {
- //Workaround for SIC Handy-Signature, because it sends result in InputStream
- final String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8");
- if (StringUtils.isNotEmpty(isReqInput)) {
- log.info("Use SIC Handy-Signature work-around!");
- sl20Result = isReqInput.substring("slcommand=".length());
-
- } else {
- log.info("NO SL2.0 commando or result FOUND.");
- throw new SL20Exception("sl20.04", null);
- }
-
- }
-
- log.trace("Received SL2.0 result: " + sl20Result);
- revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_DATAURL_IP, request.getRemoteAddr());
-
- //parse SL2.0 command/result into JSON
- try {
- sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result));
-
- } catch (final JsonParseException e) {
- log.warn("SL2.0 command or result is NOT valid JSON.", e);
- log.debug("SL2.0 msg: " + sl20Result);
- throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e);
-
- }
-
- //check on errorMessage
- final VerificationResult payLoadContainerErrorCheck = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, false);
- if (SL20JSONExtractorUtils.getStringValue(
- payLoadContainerErrorCheck.getPayload(), SL20Constants.SL20_COMMAND_CONTAINER_NAME, true)
- .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {
- log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... ");
- final JsonNode errorResult = SL20JSONExtractorUtils.extractSL20Result(payLoadContainerErrorCheck.getPayload(), joseTools, false);
- final String errorCode = SL20JSONExtractorUtils.getStringValue(errorResult,
- SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true);
- final String errorMsg = SL20JSONExtractorUtils.getStringValue(errorResult,
- SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false);
-
- log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... ", errorCode, errorMsg);
- //aTrustErrorWorkAround = true;
- throw new SL20Exception("sl20.08", new Object[] {errorCode, errorMsg});
-
- } else {
- //Receive no error - To request validation
-
- //validate reqId with inResponseTo
- final String sl20ReqId = pendingReq.getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class);
- final String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true);
- if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) {
- log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
- throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo);
- }
-
-
- //validate signature
- final VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(
- sl20ReqObj, joseTools,
- authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true));
-
- if ( (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned())) {
- if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) {
- log.info("SL20 result from VDA was not valid signed");
- throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."});
-
- } else {
- log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification is DISABLED by configuration!");
-
- }
- }
-
- payLoadContainer.getCertChain();
-
-
- //extract payloaf
- final JsonNode payLoad = payLoadContainer.getPayload();
-
-
- //handle SL2.0 response payLoad
- handleResponsePayLoad(payLoad);
-
- }
-
- } catch (final EAAFAuthenticationException e) {
- log.warn("SL2.0 processing error:", e);
- if (sl20Result != null)
- log.debug("Received SL2.0 result: " + sl20Result);
- pendingReq.setRawDataToTransaction(
- Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
- new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e));
-
- } catch (final Exception e) {
- log.warn("ERROR:", e);
- log.warn("SL2.0 Authentication FAILED with a generic error.", e);
- if (sl20Result != null)
- log.debug("Received SL2.0 result: " + sl20Result);
- pendingReq.setRawDataToTransaction(
- Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,
- new TaskExecutionException(pendingReq, e.getMessage(), e));
-
- } finally {
- //store pending request
- requestStoreage.storePendingRequest(pendingReq);
-
- //write SL2.0 response
- if (sl20ReqObj != null)
- //buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround);
- buildResponse(request, response, sl20ReqObj);
- else
- buildErrorResponse(request, response, "2000", "General transport Binding error");
-
- }
-
- } catch (final Exception e) {
- //write internal server errror 500 according to SL2.0 specification, chapter https transport binding
- log.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e);
- if (sl20Result != null)
- log.debug("Received SL2.0 result: " + sl20Result);
- try {
- response.sendError(500, "Internal Server Error.");
-
- } catch (final IOException e1) {
- log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e);
-
- }
-
- } finally {
- TransactionIDUtils.removeTransactionId();
- TransactionIDUtils.removeSessionId();
-
- }
- }
-
- protected abstract void handleResponsePayLoad(JsonNode payLoad) throws SLCommandoParserException, SL20Exception, EAAFStorageException;
-
- protected abstract String getResumeEndPoint();
-
- private void buildErrorResponse(HttpServletRequest request, HttpServletResponse response, String errorCode, String errorMsg) throws Exception {
- final ObjectNode error = SL20JSONBuilderUtils.createErrorCommandResult(errorCode, errorMsg);
- final ObjectNode errorCommand = SL20JSONBuilderUtils.createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null);
-
-
- final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericResponse(
- UUID.randomUUID().toString(),
- null,
- null,
- errorCommand ,
- null);
-
- log.trace("SL20 response to VDA: " + respContainer);
- final StringWriter writer = new StringWriter();
- writer.write(respContainer.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentLength(content.length);
- response.setContentType(ContentType.APPLICATION_JSON.toString());
- response.getOutputStream().write(content);
-
- }
-
- private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonNode sl20ReqObj) throws IOException, SL20Exception, URISyntaxException {
- //create response
- final Map<String, String> reqParameters = new HashMap<String, String>();
- reqParameters.put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId());
- final ObjectNode callReqParams = SL20JSONBuilderUtils.createCallCommandParameters(
- new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), null),
- SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,
- false,
- reqParameters);
- final ObjectNode callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams);
-
- //build first redirect command for app
- final ObjectNode redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters(
- generateICPRedirectURLForDebugging(),
- callCommand, null, true);
- final ObjectNode redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams);
-
- //build second redirect command for IDP
- final ObjectNode redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters(
- new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId()),
- redirectOneCommand, null, false);
- final ObjectNode redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams);
-
- //build generic SL2.0 response container
- final String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false);
- final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericRequest(
- UUID.randomUUID().toString(),
- transactionId,
- redirectTwoCommand,
- null);
-
- if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&
- request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
- log.debug("Client request containts 'native client' header ... ");
- log.trace("SL20 response to VDA: " + respContainer);
- final StringWriter writer = new StringWriter();
- writer.write(respContainer.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentLength(content.length);
- response.setContentType(ContentType.APPLICATION_JSON.toString());
- response.getOutputStream().write(content);
-
-
- } else {
- log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'");
-
- log.debug("Client request containts is no native client ... ");
- final URIBuilder clientRedirectURI = new URIBuilder(
- new DataURLBuilder().buildDataURL(
- pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId()));
- response.setStatus(Integer.parseInt(
- authConfig.getBasicConfiguration(
- Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,
- Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));
- response.setHeader("Location", clientRedirectURI.build().toString());
-
-
-// throw new SL20Exception("sl20.06",
-// new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"});
-
- }
- }
-
- /**
- * Generates a IPC redirect URL that is configured on IDP side
- *
- * @return IPC ReturnURL, or null if no URL is configured
- */
- private String generateICPRedirectURLForDebugging() {
- final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#";
-
- String ipcRedirectURLConfig = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL);
- if (StringUtils.isNotEmpty(ipcRedirectURLConfig)) {
- if (ipcRedirectURLConfig.contains(PATTERN_PENDING_REQ_ID)) {
- log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... ");
- ipcRedirectURLConfig = ipcRedirectURLConfig.replaceAll(
- "#PENDINGREQID#",
- EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId());
-
- }
-
- return ipcRedirectURLConfig;
- }
-
- return null;
-
- }
-
-
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java
deleted file mode 100644
index b124ada7..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.utils;
-
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.cert.X509Certificate;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-import org.jose4j.jwa.AlgorithmConstraints;
-import org.jose4j.lang.JoseException;
-
-import com.fasterxml.jackson.databind.JsonNode;
-
-import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException;
-
-public interface IJOSETools {
-
- /**
- * Create a JWS signature
- *
- * @param payLoad Payload to sign
- * @throws SLCommandoBuildException
- */
- public String createSignature(String payLoad) throws SLCommandoBuildException;
-
- /**
- * Validates a signed SL2.0 message
- *
- * @param serializedContent
- * @return
- * @throws SLCommandoParserException
- * @throws SL20Exception
- */
- @Nonnull
- public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception;
-
- /**
- * Validate a JWS signature
- *
- * @param serializedContent JWS in serialized form
- * @param trustedCerts trusted X509 certificates
- * @param constraints signature verification constraints
- * @return Signature-verification result
- * @throws JoseException
- * @throws IOException
- */
- @Nonnull
- public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts,
- @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException;
-
- /**
- * Validate a JWS signature
- *
- * @param serializedContent JWS in serialized form
- * @param trustStore with trusted X509 certificates
- * @param algconstraints signature verification constraints
- * @return Signature-verification result
- * @throws JoseException
- * @throws IOException
- * @throws KeyStoreException
- */
- @Nonnull
- public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull KeyStore trustStore,
- @Nonnull AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException;
-
- /**
- * Get the encryption certificate for SL2.0 End-to-End encryption
- *
- * @return
- */
- public X509Certificate getEncryptionCertificate();
-
- /**
- * Decrypt a serialized JWE token
- *
- * @param compactSerialization Serialized JWE token
- * @return decrypted payload
- * @throws SL20Exception
- */
- public JsonNode decryptPayload(String compactSerialization) throws SL20Exception;
-
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java
new file mode 100644
index 00000000..f04555dc
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java
@@ -0,0 +1,98 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.utils;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException;
+
+import org.jose4j.jwa.AlgorithmConstraints;
+import org.jose4j.lang.JoseException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+public interface IJoseTools {
+
+ /**
+ * Create a JWS signature.
+ *
+ *<p>This method adds the certificate chain into JOSE header.</p>
+ *
+ * @param payLoad Payload to sign
+ * @throws SlCommandoBuildException In case of a signature creation error
+ */
+ String createSignature(String payLoad) throws SlCommandoBuildException;
+
+ /**
+ * Create a JWS signature.
+ *
+ * @param payLoad Payload to sign
+ * @param addFullCertChain If <code>true</code> the full certificate chain will be added,
+ * otherwise only the X509CertSha256Fingerprint is added into JOSE header
+ * @return Signed PayLoad in serialized form
+ * @throws SlCommandoBuildException SlCommandoBuildException In case of a signature creation error
+ */
+ String createSignature(String payLoad, boolean addFullCertChain) throws SlCommandoBuildException;
+
+ /**
+ * Validates a signed SL2.0 message.
+ *
+ * @param serializedContent Serialized JWS signature
+ * @return Verification-result DAO
+ * @throws SL20Exception In case of a signature validation error
+ */
+ @Nonnull
+ VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception;
+
+ /**
+ * Validate a JWS signature.
+ *
+ * @param serializedContent JWS in serialized form
+ * @param trustedCerts trusted X509 certificates
+ * @param constraints signature verification constraints
+ * @return Signature-verification result
+ * @throws JoseException In case of a signature verification error
+ * @throws IOException In case of a general IO error
+ */
+ @Nonnull
+ VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts,
+ @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException;
+
+ /**
+ * Validate a JWS signature.
+ *
+ * @param serializedContent JWS in serialized form
+ * @param trustStore with trusted X509 certificates
+ * @param algconstraints signature verification constraints
+ * @return Signature-verification result
+ * @throws JoseException In case of a signature verification error
+ * @throws IOException In case of a general IO error
+ * @throws KeyStoreException In case of TrustStore error
+ */
+ @Nonnull
+ VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull KeyStore trustStore,
+ @Nonnull AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException;
+
+ /**
+ * Get the encryption certificate for SL2.0 End-to-End encryption.
+ *
+ * @return
+ */
+ X509Certificate getEncryptionCertificate();
+
+ /**
+ * Decrypt a serialized JWE token.
+ *
+ * @param compactSerialization Serialized JWE token
+ * @return decrypted payload
+ * @throws SL20Exception In case of a decryption error
+ */
+ JsonNode decryptPayload(String compactSerialization) throws SL20Exception;
+
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java
index b33649e1..2387a9f2 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java
@@ -18,114 +18,122 @@ import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import at.gv.egiz.eaaf.core.api.utils.IJsonMapper;
-import at.gv.egiz.eaaf.core.exceptions.EAAFJsonMapperException;
+import at.gv.egiz.eaaf.core.exceptions.EaafJsonMapperException;
public class JsonMapper implements IJsonMapper {
- private static final Logger log = LoggerFactory.getLogger(JsonMapper.class);
-
- private final ObjectMapper mapper = new ObjectMapper();
-
- /**
- * The default constructor where the default pretty printer is disabled.
- */
- public JsonMapper() {
- this(false);
-
- }
-
- /**
- * The constructor.
- * @param prettyPrint enables or disables the default pretty printer
- */
- public JsonMapper(@NonNull boolean prettyPrint) {
- log.trace("Initializing JSON object-mapper ... ");
- mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true);
- mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES , true);
- mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
- mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);
- mapper.setVisibility(PropertyAccessor.IS_GETTER, Visibility.PUBLIC_ONLY);
- if (prettyPrint) {
- mapper.enable(SerializationFeature.INDENT_OUTPUT);
- }
-
- log.debug("JSON object-mapper initialized");
-
- }
-
-
- /* (non-Javadoc)
- * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper()
- */
- public ObjectMapper getMapper() {
- return mapper;
-
- }
-
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object)
- */
- @Override
- public String serialize(Object value) throws EAAFJsonMapperException {
- try {
- return mapper.writeValueAsString(value);
-
- } catch (final JsonProcessingException e) {
- log.warn("JSON mapping FAILED with error: {}", e.getMessage());
- throw new EAAFJsonMapperException(e.getMessage(), e);
-
- }
-
- }
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String, java.lang.Class)
- */
- @Override
- public <T> Object deserialize(String value, Class<T> clazz) throws EAAFJsonMapperException {
- try {
- if (clazz != null) {
- if (clazz.isAssignableFrom(TypeReference.class))
- return mapper.readValue(value, clazz);
- else {
- final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz);
- return mapper.readValue(value, javaType);
-
- }
-
- } else
- return mapper.readValue(value, Object.class);
-
- } catch (final IOException e) {
- log.warn("JSON mapping FAILED with error: {}", e.getMessage());
- throw new EAAFJsonMapperException(e.getMessage(), e);
-
- }
-
- }
-
- @Override
- public <T> Object deserialize(InputStream is, Class<T> clazz) throws EAAFJsonMapperException {
- try {
- if (clazz != null) {
- if (clazz.isAssignableFrom(TypeReference.class))
- return mapper.readValue(is, clazz);
- else {
- final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz);
- return mapper.readValue(is, javaType);
-
- }
-
- } else
- return mapper.readValue(is, Object.class);
-
- } catch (final IOException e) {
- log.warn("JSON mapping FAILED with error: {}", e.getMessage());
- throw new EAAFJsonMapperException(e.getMessage(), e);
-
- }
-
- }
-
+ private static final Logger log = LoggerFactory.getLogger(JsonMapper.class);
+
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * The default constructor where the default pretty printer is disabled.
+ */
+ public JsonMapper() {
+ this(false);
+
+ }
+
+ /**
+ * The constructor.
+ *
+ * @param prettyPrint enables or disables the default pretty printer
+ */
+ public JsonMapper(@NonNull final boolean prettyPrint) {
+ log.trace("Initializing JSON object-mapper ... ");
+ mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true);
+ mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
+ mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
+ mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);
+ mapper.setVisibility(PropertyAccessor.IS_GETTER, Visibility.PUBLIC_ONLY);
+ if (prettyPrint) {
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ }
+
+ log.debug("JSON object-mapper initialized");
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper()
+ */
+ public ObjectMapper getMapper() {
+ return mapper;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object)
+ */
+ @Override
+ public String serialize(final Object value) throws EaafJsonMapperException {
+ try {
+ return mapper.writeValueAsString(value);
+
+ } catch (final JsonProcessingException e) {
+ log.warn("JSON mapping FAILED with error: {}", e.getMessage());
+ throw new EaafJsonMapperException(e.getMessage(), e);
+
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String,
+ * java.lang.Class)
+ */
+ @Override
+ public <T> Object deserialize(final String value, final Class<T> clazz) throws EaafJsonMapperException {
+ try {
+ if (clazz != null) {
+ if (clazz.isAssignableFrom(TypeReference.class)) {
+ return mapper.readValue(value, clazz);
+ } else {
+ final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz);
+ return mapper.readValue(value, javaType);
+
+ }
+
+ } else {
+ return mapper.readValue(value, Object.class);
+ }
+
+ } catch (final IOException e) {
+ log.warn("JSON mapping FAILED with error: {}", e.getMessage());
+ throw new EaafJsonMapperException(e.getMessage(), e);
+
+ }
+
+ }
+
+ @Override
+ public <T> Object deserialize(final InputStream is, final Class<T> clazz) throws EaafJsonMapperException {
+ try {
+ if (clazz != null) {
+ if (clazz.isAssignableFrom(TypeReference.class)) {
+ return mapper.readValue(is, clazz);
+ } else {
+ final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz);
+ return mapper.readValue(is, javaType);
+
+ }
+
+ } else {
+ return mapper.readValue(is, Object.class);
+ }
+
+ } catch (final IOException e) {
+ log.warn("JSON mapping FAILED with error: {}", e.getMessage());
+ throw new EaafJsonMapperException(e.getMessage(), e);
+
+ }
+
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java
index c07c6081..1b1f090f 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java
@@ -1,23 +1,36 @@
package at.gv.egiz.eaaf.modules.auth.sl20.utils;
import java.io.IOException;
-import java.net.MalformedURLException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
+import java.security.Provider;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.utils.X509Utils;
+import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;
+
import org.apache.commons.lang3.StringUtils;
+import org.jose4j.jca.ProviderContext;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
import org.jose4j.jwe.JsonWebEncryption;
@@ -37,384 +50,403 @@ import org.springframework.util.Base64Utils;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
-import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException;
-import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
-import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
-import at.gv.egiz.eaaf.core.impl.utils.X509Utils;
-import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException;
-
@Service
-public class JsonSecurityUtils implements IJOSETools{
- private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class);
-
- @Autowired(required=true) IConfiguration authConfig;
- private Key signPrivKey = null;
- private X509Certificate[] signCertChain = null;
-
- private Key encPrivKey = null;
- private X509Certificate[] encCertChain = null;
-
- private List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>();
-
- private static JsonMapper mapper = new JsonMapper();
-
- @PostConstruct
- protected void initalize() {
- log.info("Initialize SL2.0 authentication security constrains ... ");
- try {
- if (getKeyStoreFilePath() != null) {
- final KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),
- getKeyStorePassword());
-
- //load signing key
- signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray());
- final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias());
- signCertChain = new X509Certificate[certChainSigning.length];
- for (int i=0; i<certChainSigning.length; i++) {
- if (certChainSigning[i] instanceof X509Certificate) {
- signCertChain[i] = (X509Certificate)certChainSigning[i];
- } else
- log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType());
-
- }
-
- //load encryption key
- try {
- encPrivKey = keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray());
- if (encPrivKey != null) {
- final Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias());
- encCertChain = new X509Certificate[certChainEncryption.length];
- for (int i=0; i<certChainEncryption.length; i++) {
- if (certChainEncryption[i] instanceof X509Certificate) {
- encCertChain[i] = (X509Certificate)certChainEncryption[i];
- } else
- log.warn("NO X509 certificate for encryption: " + certChainEncryption[i].getType());
- }
- } else
- log.info("No encryption key for SL2.0 found. End-to-End encryption is not used.");
-
- } catch (final Exception e) {
- log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(), e);
-
- }
-
- //load trusted certificates
- trustedCerts = readCertsFromKeyStore(keyStore);
-
- //some short validation
- if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) {
- log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath());
- throw new SL20Exception("sl20.03", new Object[]{"Can NOT open private key for signing"});
-
- }
-
- if (signCertChain == null || signCertChain.length == 0) {
- log.info("NO certificate for SL2.0 signing. KeyStore=" + getKeyStoreFilePath());
- throw new SL20Exception("sl20.03", new Object[]{"NO certificate for SL2.0 signing"});
-
- }
-
- log.info("SL2.0 authentication security constrains initialized.");
-
- } else
- log.info("NO SL2.0 authentication security configuration. Initialization was skipped");
-
- } catch ( final Exception e) {
- log.error("SL2.0 security constrains initialization FAILED.", e);
-
- }
-
- }
-
- @Override
- public String createSignature(String payLoad) throws SLCommandoBuildException {
- try {
- final JsonWebSignature jws = new JsonWebSignature();
-
- //set payload
- jws.setPayload(payLoad);
-
- //set basic header
- jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND);
-
- //set signing information
- jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
- jws.setKey(signPrivKey);
-
- //TODO:
- jws.setCertificateChainHeaderValue(signCertChain);
- jws.setX509CertSha256ThumbprintHeaderValue(signCertChain[0]);
-
- return jws.getCompactSerialization();
-
- } catch (final JoseException e) {
- log.warn("Can NOT sign SL2.0 command.", e);
- throw new SLCommandoBuildException("Can NOT sign SL2.0 command.", e);
-
- }
-
- }
-
- @Override
- public VerificationResult validateSignature(String serializedContent, KeyStore trustStore,
- AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException {
- final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore);
- return validateSignature(serializedContent, trustedCertificates , algconstraints);
-
- }
-
- @Override
- @NonNull
- public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException {
- final JsonWebSignature jws = new JsonWebSignature();
- //set payload
- jws.setCompactSerialization(serializedContent);
-
- //set security constrains
- jws.setAlgorithmConstraints(constraints);
-
- //load signinc certs
- Key selectedKey = null;
- final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue();
- final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue();
- if (x5cCerts != null) {
- log.debug("Found x509 certificate in JOSE header ... ");
- log.trace("Sorting received X509 certificates ... ");
- final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts);
-
- if (trustedCerts.contains(sortedX5cCerts.get(0))) {
- selectedKey = sortedX5cCerts.get(0).getPublicKey();
-
- } else {
- log.info("Can NOT find JOSE certificate in truststore.");
- try {
- log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded()));
-
- } catch (final CertificateEncodingException e) {
- e.printStackTrace();
-
- }
-
- }
-
- } else if (StringUtils.isNotEmpty(x5t256)) {
- log.debug("Found x5t256 fingerprint in JOSE header .... ");
- final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts);
- selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList());
-
- } else {
- throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint");
-
- }
-
- if (selectedKey == null) {
- throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED");
-
- }
-
- //set verification key
- jws.setKey(selectedKey);
-
- //load payLoad
- return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, jws.verifySignature()) ;
-
-
- }
-
- @Override
- @Nonnull
- public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception {
- try {
- final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST,
- SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()]));
-
- final VerificationResult result = validateSignature(serializedContent, trustedCerts, algConstraints);
-
- if (!result.isValidSigned()) {
- log.info("JWS signature invalide. Stopping authentication process ...");
- log.debug("Received JWS msg: " + serializedContent);
- throw new SL20SecurityException("JWS signature invalide.");
-
- }
-
- log.debug("SL2.0 commando signature validation sucessfull");
- return result;
-
- } catch (JoseException | JsonParseException e) {
- log.warn("SL2.0 commando signature validation FAILED", e);
- throw new SL20SecurityException(new Object[]{e.getMessage()}, e);
-
- } catch (final IOException e) {
- log.warn("Decrypted SL2.0 result can not be parsed.", e);
- throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e);
-
- }
-
- }
-
-
- @Override
- public JsonNode decryptPayload(String compactSerialization) throws SL20Exception {
- try {
- final JsonWebEncryption receiverJwe = new JsonWebEncryption();
-
- //set security constrains
- receiverJwe.setAlgorithmConstraints(
- new AlgorithmConstraints(ConstraintType.WHITELIST,
- SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()])));
- receiverJwe.setContentEncryptionAlgorithmConstraints(
- new AlgorithmConstraints(ConstraintType.WHITELIST,
- SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()])));
-
- //set payload
- receiverJwe.setCompactSerialization(compactSerialization);
-
-
- //validate key from header against key from config
- final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue();
- final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue();
- if (x5cCerts != null) {
- log.debug("Found x509 certificate in JOSE header ... ");
- log.trace("Sorting received X509 certificates ... ");
- final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts);
-
- if (!sortedX5cCerts.get(0).equals(encCertChain[0])) {
- log.info("Certificate from JOSE header does NOT match encryption certificate");
- log.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString());
-
- try {
- log.debug("Cert: " + Base64Utils.encode(sortedX5cCerts.get(0).getEncoded()));
- } catch (final CertificateEncodingException e) {
- e.printStackTrace();
- }
- throw new SL20Exception("sl20.05", new Object[]{"Certificate from JOSE header does NOT match encryption certificate"});
- }
-
- } else if (StringUtils.isNotEmpty(x5t256)) {
- log.debug("Found x5t256 fingerprint in JOSE header .... ");
- final String certFingerPrint = X509Util.x5tS256(encCertChain[0]);
- if (!certFingerPrint.equals(x5t256)) {
- log.info("X5t256 from JOSE header does NOT match encryption certificate");
- log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint);
- throw new SL20Exception("sl20.05", new Object[]{"X5t256 from JOSE header does NOT match encryption certificate"});
-
- }
-
- } else {
- log.info("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint");
- throw new SLCommandoParserException("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint");
-
- }
-
- //set key
- receiverJwe.setKey(encPrivKey);
-
-
- //decrypt payload
- return mapper.getMapper().readTree(receiverJwe.getPlaintextString());
-
- } catch (final JoseException e) {
- log.warn("SL2.0 result decryption FAILED", e);
- throw new SL20SecurityException(new Object[]{e.getMessage()}, e);
-
- } catch ( final JsonParseException e) {
- log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e);
- throw new SLCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e);
-
- } catch (final IOException e) {
- log.warn("Decrypted SL2.0 result can not be parsed.", e);
- throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e);
- }
-
- }
-
-
-
- @Override
- public X509Certificate getEncryptionCertificate() {
- //TODO: maybe update after SL2.0 update on encryption certificate parts
- if (encCertChain !=null && encCertChain.length > 0)
- return encCertChain[0];
- else
- return null;
- }
-
- private String getKeyStoreFilePath() throws EAAFConfigurationException, MalformedURLException {
- return FileUtils.makeAbsoluteURL(
- authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH),
- authConfig.getConfigurationRootDirectory());
- }
-
- private String getKeyStorePassword() {
- String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD);
- if (value != null)
- value = value.trim();
-
- return value;
-
- }
-
- private String getSigningKeyAlias() {
- String value = authConfig.getBasicConfiguration(
- Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS).trim();
- if (value != null)
- value = value.trim();
-
- return value;
- }
-
- private String getSigningKeyPassword() {
- String value = authConfig.getBasicConfiguration(
- Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD).trim();
- if (value != null)
- value = value.trim();
-
- return value;
- }
-
- private String getEncryptionKeyAlias() {
- String value = authConfig.getBasicConfiguration(
- Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS).trim();
- if (value != null)
- value = value.trim();
-
- return value;
- }
-
- private String getEncryptionKeyPassword() {
- String value = authConfig.getBasicConfiguration(
- Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD).trim();
- if (value != null)
- value = value.trim();
-
- return value;
- }
-
- @Nonnull
- private List<X509Certificate> readCertsFromKeyStore(@Nonnull KeyStore keyStore) throws KeyStoreException {
- final List<X509Certificate> result = new ArrayList<>();
-
- final Enumeration<String> aliases = keyStore.aliases();
- while(aliases.hasMoreElements()) {
- final String el = aliases.nextElement();
- log.trace("Process TrustStoreEntry: " + el);
- if (keyStore.isCertificateEntry(el)) {
- final Certificate cert = keyStore.getCertificate(el);
- if (cert != null && cert instanceof X509Certificate)
- result.add((X509Certificate) cert);
- else
- log.info("Can not process entry: " + el + ". Reason: " + cert.toString());
-
- }
- }
-
- return Collections.unmodifiableList(result);
- }
-
+public class JsonSecurityUtils implements IJoseTools {
+ private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class);
+
+ private static final String FRIENDLYNAME_KEYSTORE = "SL2.0 KeyStore";
+ private static final String FRIENDLYNAME_TRUSTSTORE = "SL2.0 TrustStore";
+
+ @Autowired(required = true)
+ IConfiguration authConfig;
+ @Autowired(required = true)
+ EaafKeyStoreFactory keystoreFactory;
+
+ private Pair<KeyStore, Provider> keyStore;
+ private Pair<KeyStore, Provider> trustStore;
+
+ private static JsonMapper mapper = new JsonMapper();
+
+ @PostConstruct
+ protected void initalize() throws SL20Exception {
+ log.info("Initialize SL2.0 authentication security constrains ... ");
+ try {
+ // load KeyStore
+ final KeyStoreConfiguration keyStoreConfig = buildKeyStoreConfiguration();
+ keyStore = keystoreFactory.buildNewKeyStore(keyStoreConfig);
+
+ // load TrustStore
+ final KeyStoreConfiguration trustStoreConfig = buildTrustStoreConfiguration();
+ trustStore = keystoreFactory.buildNewKeyStore(trustStoreConfig);
+
+ // validate KeyStore entries
+ EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore.getFirst(), getSigningKeyAlias(),
+ getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE);
+ final Pair<Key, X509Certificate[]> encCredentials =
+ EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore.getFirst(), getEncryptionKeyAlias(),
+ getEncryptionKeyPassword(), false, FRIENDLYNAME_TRUSTSTORE);
+ if (encCredentials == null) {
+ log.info("No encryption key for SL2.0 found. End-to-End encryption is not used.");
+
+ }
+
+ // validate TrustStore
+ final List<X509Certificate> trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore
+ .getFirst());
+ if (trustedCerts.isEmpty()) {
+ log.info("No certificates in TrustStore: {}. Signature validation will FAIL!",
+ FRIENDLYNAME_TRUSTSTORE);
+
+ } else {
+ log.info("Find #{} certificates in TrustStore: {}",
+ trustedCerts.size(), FRIENDLYNAME_TRUSTSTORE);
+
+ }
+
+ log.info("SL2.0 authentication security constrains initialized.");
+
+ } catch (final RuntimeException e) {
+ throw e;
+
+ } catch (final Exception e) {
+ log.error("SL2.0 security constrains initialization FAILED.");
+ throw new SL20Exception("sl20.11", new Object[] { e.getMessage() }, e);
+
+ }
+
+ }
+
+ @Override
+ public String createSignature(final String payLoad) throws SlCommandoBuildException {
+ return createSignature(payLoad, true);
+
+ }
+
+ @Override
+ public String createSignature(final String payLoad, boolean addFullCertChain) throws SlCommandoBuildException {
+ try {
+ final JsonWebSignature jws = new JsonWebSignature();
+
+ // set payload
+ jws.setPayload(payLoad);
+
+ // set basic header
+ jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND);
+
+ // set signing information
+ jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
+ final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
+ keyStore.getFirst(), getSigningKeyAlias(), getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE);
+ jws.setKey(signingCred.getFirst());
+
+ // set special provider if required
+ if (keyStore.getSecond() != null) {
+ log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName());
+ final ProviderContext providerCtx = new ProviderContext();
+ providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(
+ keyStore.getSecond().getName());
+ jws.setProviderContext(providerCtx);
+
+ }
+
+ if (addFullCertChain) {
+ jws.setCertificateChainHeaderValue(signingCred.getSecond());
+
+ }
+
+ jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]);
+
+ return jws.getCompactSerialization();
+
+ } catch (final JoseException | EaafKeyAccessException e) {
+ log.warn("Can NOT sign SL2.0 command.", e);
+ throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e);
+
+ }
+
+ }
+
+ @Override
+ public VerificationResult validateSignature(final String serializedContent, final KeyStore trustStore,
+ final AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException {
+ final List<X509Certificate> trustedCertificates = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore);
+ return validateSignature(serializedContent, trustedCertificates, algconstraints);
+
+ }
+
+ @Override
+ @NonNull
+ public VerificationResult validateSignature(@Nonnull final String serializedContent,
+ @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints)
+ throws JoseException, IOException {
+ final JsonWebSignature jws = new JsonWebSignature();
+ // set payload
+ jws.setCompactSerialization(serializedContent);
+
+ // set security constrains
+ jws.setAlgorithmConstraints(constraints);
+
+ // load signinc certs
+ Key selectedKey = null;
+ final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue();
+ final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue();
+ if (x5cCerts != null) {
+ log.debug("Found x509 certificate in JOSE header ... ");
+ log.trace("Sorting received X509 certificates ... ");
+ final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts);
+
+ if (trustedCerts.contains(sortedX5cCerts.get(0))) {
+ selectedKey = sortedX5cCerts.get(0).getPublicKey();
+
+ } else {
+ log.info("Can NOT find JOSE certificate in truststore.");
+ try {
+ log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded()));
+
+ } catch (final CertificateEncodingException e) {
+ e.printStackTrace();
+
+ }
+
+ }
+
+ } else if (StringUtils.isNotEmpty(x5t256)) {
+ log.debug("Found x5t256 fingerprint in JOSE header .... ");
+ final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(
+ trustedCerts);
+ selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList());
+
+ } else {
+ throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint");
+
+ }
+
+ if (selectedKey == null) {
+ throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED");
+
+ }
+
+ // set verification key
+ jws.setKey(selectedKey);
+
+ // load payLoad
+ return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, jws.verifySignature());
+
+ }
+
+ @Override
+ @Nonnull
+ public VerificationResult validateSignature(@Nonnull final String serializedContent) throws SL20Exception {
+ try {
+ final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST,
+ SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING
+ .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()]));
+
+ final VerificationResult result =
+ validateSignature(serializedContent, EaafKeyStoreUtils.readCertsFromKeyStore(trustStore.getFirst()),
+ algConstraints);
+
+ if (!result.isValidSigned()) {
+ log.info("JWS signature invalide. Stopping authentication process ...");
+ log.debug("Received JWS msg: " + serializedContent);
+ throw new SL20SecurityException("JWS signature invalide.");
+
+ }
+
+ log.debug("SL2.0 commando signature validation sucessfull");
+ return result;
+
+ } catch (JoseException | JsonParseException | KeyStoreException e) {
+ log.warn("SL2.0 commando signature validation FAILED", e);
+ throw new SL20SecurityException(new Object[] { e.getMessage() }, e);
+
+ } catch (final IOException e) {
+ log.warn("Decrypted SL2.0 result can not be parsed.", e);
+ throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e);
+
+ }
+
+ }
+
+ @Override
+ public JsonNode decryptPayload(final String compactSerialization) throws SL20Exception {
+ try {
+ final JsonWebEncryption receiverJwe = new JsonWebEncryption();
+
+ // set security constrains
+ receiverJwe.setAlgorithmConstraints(
+ new AlgorithmConstraints(ConstraintType.WHITELIST,
+ SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION
+ .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()])));
+ receiverJwe.setContentEncryptionAlgorithmConstraints(
+ new AlgorithmConstraints(ConstraintType.WHITELIST, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION
+ .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()])));
+
+ // set payload
+ receiverJwe.setCompactSerialization(compactSerialization);
+
+ final Pair<Key, X509Certificate[]> encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
+ keyStore.getFirst(), getEncryptionKeyAlias(), getEncryptionKeyPassword(), true,
+ FRIENDLYNAME_KEYSTORE);
+
+ // validate key from header against key from config
+ final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue();
+ final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue();
+ if (x5cCerts != null) {
+ log.debug("Found x509 certificate in JOSE header ... ");
+ log.trace("Sorting received X509 certificates ... ");
+ final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts);
+
+ if (!sortedX5cCerts.get(0).equals(encryptionCred.getSecond()[0])) {
+ log.info("Certificate from JOSE header does NOT match encryption certificate");
+
+ try {
+
+ log.debug("JOSE certificate: {}", Base64Utils.encode(sortedX5cCerts.get(0).getEncoded()));
+ } catch (final CertificateEncodingException e) {
+ e.printStackTrace();
+ }
+ throw new SL20Exception("sl20.05",
+ new Object[] { "Certificate from JOSE header does NOT match encryption certificate" });
+ }
+
+ } else if (StringUtils.isNotEmpty(x5t256)) {
+ log.debug("Found x5t256 fingerprint in JOSE header .... ");
+ final String certFingerPrint = X509Util.x5tS256(encryptionCred.getSecond()[0]);
+ if (!certFingerPrint.equals(x5t256)) {
+ log.info("X5t256 from JOSE header does NOT match encryption certificate");
+ log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint);
+ throw new SL20Exception("sl20.05",
+ new Object[] { "X5t256 from JOSE header does NOT match encryption certificate" });
+
+ }
+
+ } else {
+ log.info("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint");
+ throw new SlCommandoParserException(
+ "Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint");
+
+ }
+
+ // set key
+ receiverJwe.setKey(encryptionCred.getFirst());
+
+ // decrypt payload
+ return mapper.getMapper().readTree(receiverJwe.getPlaintextString());
+
+ } catch (final JoseException | EaafKeyAccessException e) {
+ log.warn("SL2.0 result decryption FAILED", e);
+ throw new SL20SecurityException(new Object[] { e.getMessage() }, e);
+
+ } catch (final JsonParseException e) {
+ log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e);
+ throw new SlCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e);
+
+ } catch (final IOException e) {
+ log.warn("Decrypted SL2.0 result can not be parsed.", e);
+ throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e);
+
+ }
+ }
+
+ @Override
+ public X509Certificate getEncryptionCertificate() {
+ Pair<Key, X509Certificate[]> encryptionCred;
+ try {
+ encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore.getFirst(),
+ getEncryptionKeyAlias(), getEncryptionKeyPassword(), false, FRIENDLYNAME_KEYSTORE);
+ if (encryptionCred != null && encryptionCred.getSecond().length > 0) {
+ return encryptionCred.getSecond()[0];
+
+ }
+
+ } catch (final EaafKeyAccessException e) {
+ log.trace("Exception is skipped because Encryption is not mandatory on this level", e);
+
+ }
+
+ return null;
+
+ }
+
+ private KeyStoreConfiguration buildKeyStoreConfiguration() throws EaafConfigurationException {
+ final KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName(FRIENDLYNAME_KEYSTORE);
+
+ config.setKeyStoreType(authConfig.getBasicConfiguration(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE),
+ KeyStoreType.JKS.getKeyStoreType()));
+ config.setKeyStoreName(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_NAME));
+ config.setSoftKeyStoreFilePath(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH));
+ config.setSoftKeyStorePassword(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD));
+
+ // validate configuration state
+ config.validate();
+
+ return config;
+
+ }
+
+ private KeyStoreConfiguration buildTrustStoreConfiguration() throws EaafConfigurationException {
+ final KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName(FRIENDLYNAME_TRUSTSTORE);
+
+ config.setKeyStoreType(authConfig.getBasicConfiguration(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE),
+ KeyStoreType.JKS.getKeyStoreType()));
+ config.setKeyStoreName(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_NAME));
+ config.setSoftKeyStoreFilePath(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PATH));
+ config.setSoftKeyStorePassword(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD));
+
+ // validate configuration state
+ config.validate();
+
+ return config;
+ }
+
+ private String getSigningKeyAlias() {
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS);
+ if (value != null) {
+ value = value.trim();
+ }
+
+ return value;
+ }
+
+ private char[] getSigningKeyPassword() {
+ final String value = authConfig.getBasicConfiguration(
+ Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD);
+ if (value != null) {
+ return value.trim().toCharArray();
+ }
+
+ return null;
+ }
+
+ private String getEncryptionKeyAlias() {
+ String value = authConfig.getBasicConfiguration(
+ Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS);
+ if (value != null) {
+ value = value.trim();
+ }
+
+ return value;
+ }
+
+ private char[] getEncryptionKeyPassword() {
+ final String value = authConfig.getBasicConfiguration(
+ Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD);
+ if (value != null) {
+ return value.trim().toCharArray();
+ }
+
+ return null;
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java
index 06c36cff..01316b9b 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java
@@ -1,6 +1,7 @@
package at.gv.egiz.eaaf.modules.auth.sl20.utils;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
@@ -8,234 +9,255 @@ import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
import org.jose4j.jws.AlgorithmIdentifiers;
public class SL20Constants {
- public static final int CURRENT_SL20_VERSION = 10;
-
- //http binding parameters
- public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand";
- public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command";
-
- public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl";
- public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID";
-
- public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType";
- public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA";
- public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp";
-
- public static final String HTTP_HEADER_SL20_RESP = "X-SL20Operation";
-
-
- //*******************************************************************************************
- //JSON signing and encryption headers
- public static final String JSON_ALGORITHM = "alg";
- public static final String JSON_CONTENTTYPE = "cty";
- public static final String JSON_X509_CERTIFICATE = "x5c";
- public static final String JSON_X509_FINGERPRINT = "x5t#S256";
- public static final String JSON_ENCRYPTION_PAYLOAD = "enc";
-
- public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256;
- public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512;
- public static final String JSON_ALGORITHM_SIGNING_ES256 = AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256;
- public static final String JSON_ALGORITHM_SIGNING_ES512 = AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512;
- public static final String JSON_ALGORITHM_SIGNING_PS256 = AlgorithmIdentifiers.RSA_PSS_USING_SHA256;
- public static final String JSON_ALGORITHM_SIGNING_PS512 = AlgorithmIdentifiers.RSA_PSS_USING_SHA512;
-
- public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Arrays.asList(
- JSON_ALGORITHM_SIGNING_RS256,
- JSON_ALGORITHM_SIGNING_RS512,
- JSON_ALGORITHM_SIGNING_ES256,
- JSON_ALGORITHM_SIGNING_ES512,
- JSON_ALGORITHM_SIGNING_PS256,
- JSON_ALGORITHM_SIGNING_PS512
- );
-
- public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = KeyManagementAlgorithmIdentifiers.RSA_OAEP;
- public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 = KeyManagementAlgorithmIdentifiers.RSA_OAEP_256;
-
- public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Arrays.asList(
- JSON_ALGORITHM_ENC_KEY_RSAOAEP,
- JSON_ALGORITHM_ENC_KEY_RSAOAEP256
- );
-
- public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256;
- public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 = ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512;
- public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM = ContentEncryptionAlgorithmIdentifiers.AES_128_GCM;
- public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM = ContentEncryptionAlgorithmIdentifiers.AES_256_GCM;
-
- public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Arrays.asList(
- JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256,
- JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512,
- JSON_ALGORITHM_ENC_PAYLOAD_A128GCM,
- JSON_ALGORITHM_ENC_PAYLOAD_A256GCM
- );
-
-
- //*********************************************************************************************
- //Object identifier for generic transport container
- public static final String SL20_CONTENTTYPE_SIGNED_COMMAND ="application/sl2.0;command";
- public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT ="application/sl2.0;result";
-
- public static final String SL20_VERSION = "v";
- public static final String SL20_REQID = "reqID";
- public static final String SL20_RESPID = "respID";
- public static final String SL20_INRESPTO = "inResponseTo";
- public static final String SL20_TRANSACTIONID = "transactionID";
- public static final String SL20_PAYLOAD = "payload";
- public static final String SL20_SIGNEDPAYLOAD = "signedPayload";
-
- //Generic Object identifier for commands
- public static final String SL20_COMMAND_CONTAINER_NAME = "name";
- public static final String SL20_COMMAND_CONTAINER_PARAMS = "params";
- public static final String SL20_COMMAND_CONTAINER_RESULT = "result";
- public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult";
-
- //COMMAND Object identifier
- public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect";
- public static final String SL20_COMMAND_IDENTIFIER_CALL = "call";
- public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error";
- @Deprecated public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID";
- public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent";
- //public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = "qualifiedSig";
-
- public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate";
- public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES";
-
-
- public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey";
- public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert";
-
- public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword";
- public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth";
- public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor";
-
- //*****COMMAND parameter identifier******
- //general Identifier
- public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value";
- public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key";
- public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl";
- public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc";
- public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc";
-
- //Redirect command
- public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url";
- public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command";
- public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand";
- public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect";
-
- //Call command
- public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL;
- public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method";
- public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get";
- public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post";
- public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = "includeTransactionID";
- public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams";
-
- //error command
- public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode";
- public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage";
-
- //qualified eID command
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID";
- public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes";
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE";
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID";
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME";
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE";
- public static final String SL20_COMMAND_PARAM_EID_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
- public static final String SL20_COMMAND_PARAM_EID_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK";
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK";
- public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL";
- @Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL";
-
- public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID";
- public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent";
- public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS";
- public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ";
- public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent";
-
- //qualified Signature comamnd
-// public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
-// public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
-
-
- //getCertificate
- public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId";
- public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
- public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
- public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c";
-
- //createCAdES Signture
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = "padesComatibility";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = "excludedByteRange";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature";
-
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L";
- public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A";
-
-
-
- //create binding key command
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = "reqUserPassword";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
-
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1";
-
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = "useSecureElement";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = "needUserAuth";
-
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = "attCert";
- public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass";
-
-
- //store binding certificate command
- public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c";
- public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success";
- public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK";
-
- // Username and password authentication
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg";
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain";
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2";
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID = SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID;
- public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD = SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD;
-
- //JWS Token authentication
- public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce";
- public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData";
- public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl";
- public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
- public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE = SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE;
-
- //QR-Code authentication
- public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode";
- public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
-
+ public static final int CURRENT_SL20_VERSION = 10;
+
+ // http binding parameters
+ public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand";
+ public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command";
+
+ public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl";
+ public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID";
+
+ public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType";
+ public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA";
+ public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp";
+
+ public static final String HTTP_HEADER_SL20_RESP = "X-SL20Operation";
+
+ // *******************************************************************************************
+ // JSON signing and encryption headers
+ public static final String JSON_ALGORITHM = "alg";
+ public static final String JSON_CONTENTTYPE = "cty";
+ public static final String JSON_X509_CERTIFICATE = "x5c";
+ public static final String JSON_X509_FINGERPRINT = "x5t#S256";
+ public static final String JSON_ENCRYPTION_PAYLOAD = "enc";
+
+ public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256;
+ public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512;
+ public static final String JSON_ALGORITHM_SIGNING_ES256 =
+ AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256;
+ public static final String JSON_ALGORITHM_SIGNING_ES512 =
+ AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512;
+ public static final String JSON_ALGORITHM_SIGNING_PS256 = AlgorithmIdentifiers.RSA_PSS_USING_SHA256;
+ public static final String JSON_ALGORITHM_SIGNING_PS512 = AlgorithmIdentifiers.RSA_PSS_USING_SHA512;
+
+ public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList(
+ Arrays.asList(JSON_ALGORITHM_SIGNING_RS256, JSON_ALGORITHM_SIGNING_RS512, JSON_ALGORITHM_SIGNING_ES256,
+ JSON_ALGORITHM_SIGNING_ES512, JSON_ALGORITHM_SIGNING_PS256, JSON_ALGORITHM_SIGNING_PS512));
+
+ public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = KeyManagementAlgorithmIdentifiers.RSA_OAEP;
+ public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 =
+ KeyManagementAlgorithmIdentifiers.RSA_OAEP_256;
+
+ public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Collections
+ .unmodifiableList(Arrays.asList(JSON_ALGORITHM_ENC_KEY_RSAOAEP, JSON_ALGORITHM_ENC_KEY_RSAOAEP256));
+
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 =
+ ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256;
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 =
+ ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512;
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM =
+ ContentEncryptionAlgorithmIdentifiers.AES_128_GCM;
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM =
+ ContentEncryptionAlgorithmIdentifiers.AES_256_GCM;
+
+ public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Collections
+ .unmodifiableList(Arrays.asList(JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256,
+ JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512,
+ JSON_ALGORITHM_ENC_PAYLOAD_A128GCM, JSON_ALGORITHM_ENC_PAYLOAD_A256GCM));
+
+ // *********************************************************************************************
+ // Object identifier for generic transport container
+ public static final String SL20_CONTENTTYPE_SIGNED_COMMAND = "application/sl2.0;command";
+ public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT = "application/sl2.0;result";
+
+ public static final String SL20_VERSION = "v";
+ public static final String SL20_REQID = "reqID";
+ public static final String SL20_RESPID = "respID";
+ public static final String SL20_INRESPTO = "inResponseTo";
+ public static final String SL20_TRANSACTIONID = "transactionID";
+ public static final String SL20_PAYLOAD = "payload";
+ public static final String SL20_SIGNEDPAYLOAD = "signedPayload";
+
+ // Generic Object identifier for commands
+ public static final String SL20_COMMAND_CONTAINER_NAME = "name";
+ public static final String SL20_COMMAND_CONTAINER_PARAMS = "params";
+ public static final String SL20_COMMAND_CONTAINER_RESULT = "result";
+ public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult";
+
+ // COMMAND Object identifier
+ public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect";
+ public static final String SL20_COMMAND_IDENTIFIER_CALL = "call";
+ public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error";
+ @Deprecated
+ public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID";
+ public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent";
+ // public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG =
+ // "qualifiedSig";
+
+ public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate";
+ public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES";
+
+ public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey";
+ public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert";
+
+ public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword";
+ public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth";
+ public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor";
+
+ // *****COMMAND parameter identifier******
+ // general Identifier
+ public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key";
+ public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl";
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc";
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc";
+
+ // Redirect command
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect";
+
+ // Call command
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL;
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = "includeTransactionID";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams";
+
+ // error command
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode";
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage";
+
+ // qualified eID command
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID";
+ public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE";
+ public static final String SL20_COMMAND_PARAM_EID_X5CENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_EID_JWKCENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK";
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL";
+
+ public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID";
+ public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS";
+ @Deprecated
+ public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ";
+ public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent";
+ public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_QCBIND = "qcBind";
+
+ // qualified Signature comamnd
+ // public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL =
+ // SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ // public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC =
+ // SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+
+ // getCertificate
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId";
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c";
+
+ // createCAdES Signture
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = "padesComatibility";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = "excludedByteRange";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature";
+
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A";
+
+ // create binding key command
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = "reqUserPassword";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1";
+
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = "useSecureElement";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = "needUserAuth";
+
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = "attCert";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass";
+
+ // store binding certificate command
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c";
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success";
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK";
+
+ // Username and password authentication
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg";
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain";
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2";
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL =
+ SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC =
+ SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID =
+ SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID;
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD =
+ SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD;
+
+ // JWS Token authentication
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce";
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData";
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl";
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE =
+ SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE;
+
+ // QR-Code authentication
+ public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode";
+ public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+
+
+
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java
index 4d8cabb7..1d7c9646 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java
@@ -18,46 +18,47 @@ import org.springframework.http.MediaType;
import com.fasterxml.jackson.databind.JsonNode;
public class SL20HttpBindingUtils {
- private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class);
-
- /**
- * Write SL2.0 response into http-response object
- *
- * @param httpReq Current http request
- * @param httpResp Current http response
- * @param sl20Forward SL2.0 command that should be written to response
- * @param redirectURL SL2.0 redirect URL in case of SL2.0 redirect command and no native client (see SL2.0 specification)
- * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command and no native client (see SL2.0 specification)
- * @throws IOException
- * @throws URISyntaxException
- */
- public static void writeIntoResponse(@Nonnull HttpServletRequest httpReq, @Nonnull HttpServletResponse httpResp,
- @Nonnull JsonNode sl20Forward, @Nullable String redirectURL,
- @Nonnull int httpCodeRedirect) throws IOException, URISyntaxException {
- //forward SL2.0 command
- httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION);
-
- if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&
- httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
- log.debug("Client request containts 'native client' header ... ");
- final StringWriter writer = new StringWriter();
- writer.write(sl20Forward.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
- httpResp.setStatus(HttpServletResponse.SC_OK);
- httpResp.setContentLength(content.length);
- httpResp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
- httpResp.getOutputStream().write(content);
-
- } else {
- log.debug("Client request containts is no native client ... ");
- final URIBuilder clientRedirectURI = new URIBuilder(redirectURL);
- clientRedirectURI.addParameter(
- SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM,
- Base64Url.encode(sl20Forward.toString().getBytes()));
- httpResp.setStatus(httpCodeRedirect);
- httpResp.setHeader("Location", clientRedirectURI.build().toString());
-
- }
-
- }
+ private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class);
+
+ /**
+ * Write SL2.0 response into http-response object
+ *
+ * @param httpReq Current http request
+ * @param httpResp Current http response
+ * @param sl20Forward SL2.0 command that should be written to response
+ * @param redirectUrl SL2.0 redirect URL in case of SL2.0 redirect command
+ * and no native client (see SL2.0 specification)
+ * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command
+ * and no native client (see SL2.0 specification)
+ * @throws IOException In case of an IO error
+ * @throws URISyntaxException In case of a wrong URL
+ */
+ public static void writeIntoResponse(@Nonnull final HttpServletRequest httpReq,
+ @Nonnull final HttpServletResponse httpResp, @Nonnull final JsonNode sl20Forward,
+ @Nullable final String redirectUrl, @Nonnull final int httpCodeRedirect) throws IOException, URISyntaxException {
+ // forward SL2.0 command
+ httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION);
+
+ if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && httpReq
+ .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
+ log.debug("Client request containts 'native client' header ... ");
+ final StringWriter writer = new StringWriter();
+ writer.write(sl20Forward.toString());
+ final byte[] content = writer.toString().getBytes("UTF-8");
+ httpResp.setStatus(HttpServletResponse.SC_OK);
+ httpResp.setContentLength(content.length);
+ httpResp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
+ httpResp.getOutputStream().write(content);
+
+ } else {
+ log.debug("Client request containts is no native client ... ");
+ final URIBuilder clientRedirectUri = new URIBuilder(redirectUrl);
+ clientRedirectUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM,
+ Base64Url.encode(sl20Forward.toString().getBytes("UTF-8")));
+ httpResp.setStatus(httpCodeRedirect);
+ httpResp.setHeader("Location", clientRedirectUri.build().toString());
+
+ }
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java
deleted file mode 100644
index ba069ac7..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java
+++ /dev/null
@@ -1,640 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.utils;
-
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException;
-
-public class SL20JSONBuilderUtils {
-
- private static JsonMapper mapper = new JsonMapper();
-
- /**
- * Create command request
- * @param name
- * @param params
- * @throws SLCommandoBuildException
- * @return
- */
- public static ObjectNode createCommand(String name, ObjectNode params) throws SLCommandoBuildException {
-
- final ObjectNode command = mapper.getMapper().createObjectNode();
- addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
- addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);
- return command;
-
- }
-
- /**
- * Create signed command request
- *
- * @param name
- * @param params
- * @param signer
- * @return
- * @throws SLCommandoBuildException
- */
- public static String createSignedCommand(String name, ObjectNode params, IJOSETools signer) throws SLCommandoBuildException {
- final ObjectNode command = mapper.getMapper().createObjectNode();
- addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
- addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);
- return signer.createSignature(command.toString());
-
- }
-
-
- /**
- * Create encrypted command result
- *
- * @param result
- * @param encrypter
- * @return
- * @throws SLCommandoBuildException
- */
- public static String createEncryptedCommandoResult(ObjectNode result, JsonSecurityUtils encrypter) throws SLCommandoBuildException {
- //TODO: add real implementation
- //create header and footer
- final String dummyHeader = createJsonEncryptionHeader(encrypter).toString();
- final String payLoad = result.toString();
- final String dummyFooter = createJsonSignedFooter(encrypter);
-
- return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "."
- + Base64.getUrlEncoder().encodeToString(payLoad.getBytes()) + "."
- + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes());
-
- }
-
-
- /**
- * Create command result
- *
- * @param name
- * @param result
- * @param encryptedResult
- * @throws SLCommandoBuildException
- * @return
- */
- public static ObjectNode createCommandResponse(String name, ObjectNode result, String encryptedResult) throws SLCommandoBuildException {
- final ObjectNode command = mapper.getMapper().createObjectNode();
- addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
- addOnlyOnceOfTwo(command,
- SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,
- result, encryptedResult);
- return command;
-
- }
-
- /**
- * Create command result
- *
- * @param name
- * @param result
- * @param encryptedResult
- * @throws SLCommandoBuildException
- * @return
- */
- public static String createSignedCommandResponse(String name, ObjectNode result, String encryptedResult, JsonSecurityUtils signer) throws SLCommandoBuildException {
- final ObjectNode command = mapper.getMapper().createObjectNode();
- addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
- addOnlyOnceOfTwo(command,
- SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,
- result, encryptedResult);
- final String encodedCommand = command.toString();
-
- //TODO: add real implementation
- //create header and footer
- final String dummyHeader = createJsonSignedHeader(signer).toString();
- final String dummyFooter = createJsonSignedFooter(signer);
-
- return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "."
- + Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes()) + "."
- + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes());
-
- }
-
- /**
- * Create parameters for Redirect command
- *
- * @param url
- * @param command
- * @param signedCommand
- * @param ipcRedirect
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createRedirectCommandParameters(String url, ObjectNode command, ObjectNode signedCommand, Boolean ipcRedirect) throws SLCommandoBuildException{
- final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode();
- addOnlyOnceOfTwo(redirectReqParams,
- SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND,
- command, signedCommand);
- addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false);
- addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, ipcRedirect, false);
- return redirectReqParams;
-
- }
-
- /**
- * Create parameters for Call command
- *
- * @param url
- * @param method
- * @param includeTransactionId
- * @param reqParameters
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createCallCommandParameters(String url, String method, Boolean includeTransactionId, Map<String, String> reqParameters) throws SLCommandoBuildException {
- final ObjectNode callReqParams = mapper.getMapper().createObjectNode();
- addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true);
- addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true);
- addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, false);
- addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters);
- return callReqParams;
-
- }
-
- /**
- * Create result for Error command
- *
- * @param errorCode
- * @param errorMsg
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createErrorCommandResult(String errorCode, String errorMsg) throws SLCommandoBuildException {
- final ObjectNode result = mapper.getMapper().createObjectNode();
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true);
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true);
- return result;
-
- }
-
- /**
- * Create parameters for qualifiedeID command
- *
- * @param consentTemplateId Identifier of the template that is used for consent visualization
- * @param consent Consent that has to be signed by user
- * @param dataUrl
- * @param additionalReqParameters
- * @param x5cEnc
- * @return
- * @throws CertificateEncodingException
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createQualifiedeEIDConsent(String consentTemplateId, byte[] consent, String dataUrl,
- X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException {
- final ObjectNode params = mapper.getMapper().createObjectNode();
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true);
- addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true);
- addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);
- return params;
-
- }
-
-
- /**
- * Create parameters for qualifiedeID command
- *
- * @param authBlockId
- * @param dataUrl
- * @param additionalReqParameters
- * @param x5cEnc
- * @return
- * @throws CertificateEncodingException
- * @throws SLCommandoBuildException
- */
- @Deprecated
- public static ObjectNode createQualifiedeIDCommandParameters(String authBlockId, String dataUrl,
- Map<String, String> additionalReqParameters, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException {
- final ObjectNode params = mapper.getMapper().createObjectNode();
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true);
- addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters);
- addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);
- return params;
-
- }
-
- /**
- * Create result for qualifiedeID command
- *
- * @param idl
- * @param authBlock
- * @param ccsURL
- * @param LoA
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createQualifiedeIDCommandResult(byte[] idl, byte[] authBlock, String ccsURL, String LoA) throws SLCommandoBuildException {
- final ObjectNode result = mapper.getMapper().createObjectNode();
- addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true);
- addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true);
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsURL, true);
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, LoA, true);
- return result;
-
- }
-
-
- /**
- * Create Binding-Key command parameters
- *
- * @param kontoId
- * @param subjectName
- * @param keySize
- * @param keyAlg
- * @param policies
- * @param dataUrl
- * @param x5cVdaTrust
- * @param reqUserPassword
- * @param x5cEnc
- * @return
- * @throws SLCommandoBuildException
- * @throws CertificateEncodingException
- */
- public static ObjectNode createBindingKeyCommandParams(String kontoId, String subjectName, int keySize, String keyAlg,
- Map<String, String> policies, String dataUrl, X509Certificate x5cVdaTrust, Boolean reqUserPassword, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException {
- final ObjectNode params = mapper.getMapper().createObjectNode();
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true);
- addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true);
- addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true);
- addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust, false);
- addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, reqUserPassword, false);
- addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false);
- return params;
-
- }
-
- /**
- * Create Binding-Key command result
- *
- * @param appId
- * @param csr
- * @param attCert
- * @param password
- * @return
- * @throws SLCommandoBuildException
- * @throws CertificateEncodingException
- */
- public static ObjectNode createBindingKeyCommandResult(String appId, byte[] csr, X509Certificate attCert, byte[] password) throws SLCommandoBuildException, CertificateEncodingException {
- final ObjectNode result = mapper.getMapper().createObjectNode();
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true);
- addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true);
- addSingleCertificateElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false);
- addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false);
- return result;
-
- }
-
- /**
- * Create Store Binding-Certificate command parameters
- *
- * @param cert
- * @param dataUrl
- * @return
- * @throws CertificateEncodingException
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createStoreBindingCertCommandParams(X509Certificate cert, String dataUrl) throws CertificateEncodingException, SLCommandoBuildException {
- final ObjectNode params = mapper.getMapper().createObjectNode();
- addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true);
- return params;
-
- }
-
- /**
- * Create Store Binding-Certificate command result
- *
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SLCommandoBuildException {
- final ObjectNode result = mapper.getMapper().createObjectNode();
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS,
- SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true);
- return result;
-
- }
-
-
- /**
- * Create idAndPassword command parameters
- *
- * @param keyAlg
- * @param dataUrl
- * @param x5cEnc
- * @return
- * @throws SLCommandoBuildException
- * @throws CertificateEncodingException
- */
- public static ObjectNode createIdAndPasswordCommandParameters(String keyAlg, String dataUrl, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException {
- final ObjectNode params = mapper.getMapper().createObjectNode();
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true);
- addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false);
- return params;
-
- }
-
- /**
- * Create idAndPassword command result
- *
- * @param kontoId
- * @param password
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createIdAndPasswordCommandResult(String kontoId, byte[] password) throws SLCommandoBuildException {
- final ObjectNode result = mapper.getMapper().createObjectNode();
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true);
- addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true);
- return result;
-
- }
-
- /**
- * Create JWS Token Authentication command
- *
- * @param nonce
- * @param dataUrl
- * @param displayData
- * @param displayUrl
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createJwsTokenAuthCommandParams(String nonce, String dataUrl, List<String> displayData, List<String> displayUrl) throws SLCommandoBuildException {
- final ObjectNode params = mapper.getMapper().createObjectNode();
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true);
- addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true);
- addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData);
- addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl);
- return params;
-
- }
-
- /**
- * Create JWS Token Authentication command result
- *
- * @param nonce
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createJwsTokenAuthCommandResult(String nonce) throws SLCommandoBuildException {
- final ObjectNode result = mapper.getMapper().createObjectNode();
- addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true);
- return result;
-
- }
-
-
- /**
- * Create Generic Request Container
- *
- * @param reqId
- * @param transactionId
- * @param payLoad
- * @param signedPayload
- * @return
- * @throws SLCommandoBuildException
- */
- public static ObjectNode createGenericRequest(String reqId, String transactionId, ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException {
- final ObjectNode req = mapper.getMapper().createObjectNode();
- addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);
- addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true);
- addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);
- addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,
- payLoad, signedPayload);
- return req;
-
- }
-
- /**
- * Create Generic Response Container
- *
- * @param respId
- * @param inResponseTo
- * @param transactionId
- * @param payLoad
- * @param signedPayload
- * @return
- * @throws SLCommandoBuildException
- */
- public static final ObjectNode createGenericResponse(String respId, String inResponseTo, String transactionId,
- ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException {
- final ObjectNode req = mapper.getMapper().createObjectNode();
- addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);
- addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true);
- addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false);
- addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);
- addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,
- payLoad, signedPayload);
- return req;
-
- }
-
- /**
- * Add one element of two possible elements <br>
- * This method adds either the first element or the second element to parent JSON, but never both.
- *
- * @param parent Parent JSON element
- * @param firstKeyId first element Id
- * @param secondKeyId second element Id
- * @param first first element
- * @param second second element
- * @throws SLCommandoBuildException
- */
- public static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, String second) throws SLCommandoBuildException {
- if (first == null && (second == null || second.isEmpty()))
- throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL");
-
- else if (first != null && second != null)
- throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE");
-
- else if (first != null)
- parent.set(firstKeyId, first);
-
- else if (second != null && !second.isEmpty())
- parent.put(secondKeyId, second);
-
- else
- throw new SLCommandoBuildException("Internal build error");
- }
-
-
-
- //TODO!!!!
- private static ObjectNode createJsonSignedHeader(JsonSecurityUtils signer) throws SLCommandoBuildException {
- final ObjectNode header = mapper.getMapper().createObjectNode();
- addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true);
- addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true);
- addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT));
-
- return header;
- }
-
- //TODO!!!!
- private static ObjectNode createJsonEncryptionHeader(JsonSecurityUtils signer) throws SLCommandoBuildException {
- final ObjectNode header = mapper.getMapper().createObjectNode();
- addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true);
- addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true);
- addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, true);
- addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true);
-
- return header;
- }
-
- //TODO!!!!
- private static String createJsonSignedFooter(JsonSecurityUtils signer) {
- return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n" +
- " AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n" +
- " BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n" +
- " 0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n" +
- " hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" +
- " p0igcN_IoypGlUPQGe77Rw";
- }
-
-
-
- private static void addArrayOfStrings(ObjectNode parent, String keyId, List<String> values) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
- if (values != null) {
- final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode();
- parent.set(keyId, callReqParamsArray );
- for(final String el : values)
- callReqParamsArray.add(el);
-
- }
- }
-
-
- private static void addArrayOfStringElements(ObjectNode parent, String keyId, Map<String, String> keyValuePairs) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
- if (keyValuePairs != null) {
- final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode();
- parent.set(keyId, callReqParamsArray);
-
- for(final Entry<String, String> el : keyValuePairs.entrySet()) {
- final ObjectNode callReqParams = mapper.getMapper().createObjectNode();
- callReqParams.put(el.getKey(), el.getValue());
- callReqParamsArray.add(callReqParams);
-
- }
- }
- }
-
- private static void addSingleCertificateElement(ObjectNode parent, String keyId, X509Certificate cert, boolean isRequired) throws CertificateEncodingException, SLCommandoBuildException {
- if (cert != null)
- addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired);
-
- else if (isRequired)
- throw new SLCommandoBuildException(keyId + " is marked as REQUIRED");
-
- }
-
-
-
- private static void addSingleByteElement(ObjectNode parent, String keyId, byte[] value, boolean isRequired) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
-
- if (isRequired && value == null)
- throw new SLCommandoBuildException(keyId + " has NULL value");
-
- else if (value != null)
- parent.put(keyId, Base64.getEncoder().encodeToString(value));
-
- }
-
- private static void addSingleBooleanElement(ObjectNode parent, String keyId, Boolean value, boolean isRequired) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
-
- if (isRequired && value == null)
- throw new SLCommandoBuildException(keyId + " has a NULL value");
-
- else if (value != null)
- parent.put(keyId, value);
-
- }
-
- private static void addSingleNumberElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
-
- if (isRequired && value == null)
- throw new SLCommandoBuildException(keyId + " has a NULL value");
-
- else if (value != null)
- parent.put(keyId, value);;
-
- }
-
- private static void addSingleStringElement(ObjectNode parent, String keyId, String value, boolean isRequired) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
-
- if (isRequired && (value == null || value.isEmpty()))
- throw new SLCommandoBuildException(keyId + " has an empty value");
-
- else if (value != null && !value.isEmpty())
- parent.put(keyId, value);
-
- }
-
- private static void addSingleIntegerElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
-
- if (isRequired && value == null)
- throw new SLCommandoBuildException(keyId + " has an empty value");
-
- else if (value != null)
- parent.put(keyId, value);
-
- }
-
- private static void addSingleJSONElement(ObjectNode parent, String keyId, ObjectNode element, boolean isRequired) throws SLCommandoBuildException {
- validateParentAndKey(parent, keyId);
-
- if (isRequired && element == null)
- throw new SLCommandoBuildException("No commando name included");
-
- else if (element != null)
- parent.set(keyId, element);
-
- }
-
- private static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, ObjectNode second) throws SLCommandoBuildException {
- if (first == null && second == null)
- throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL");
-
- else if (first != null && second != null)
- throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE");
-
- else if (first != null)
- parent.set(firstKeyId, first);
-
- else if (second != null)
- parent.set(secondKeyId, second);
-
- else
- throw new SLCommandoBuildException("Internal build error");
- }
-
- private static void validateParentAndKey(ObjectNode parent, String keyId) throws SLCommandoBuildException {
- if (parent == null)
- throw new SLCommandoBuildException("NO parent JSON element");
-
- if (keyId == null || keyId.isEmpty())
- throw new SLCommandoBuildException("NO JSON element identifier");
- }
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java
deleted file mode 100644
index 314dde17..00000000
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java
+++ /dev/null
@@ -1,368 +0,0 @@
-package at.gv.egiz.eaaf.modules.auth.sl20.utils;
-
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.util.EntityUtils;
-import org.jose4j.base64url.Base64Url;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException;
-
-public class SL20JSONExtractorUtils {
- private static final Logger log = LoggerFactory.getLogger(SL20JSONExtractorUtils.class);
- private static JsonMapper mapper = new JsonMapper();
-
-
- /**
- * Extract String value from JSON
- *
- * @param input
- * @param keyID
- * @param isRequired
- * @return
- * @throws SLCommandoParserException
- */
- public static String getStringValue(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException {
- try {
- final JsonNode internal = getAndCheck(input, keyID, isRequired);
-
- if (internal != null)
- return internal.asText();
- else
- return null;
-
- } catch (final SLCommandoParserException e) {
- throw e;
-
- } catch (final Exception e) {
- throw new SLCommandoParserException("Can not extract String value with keyId: " + keyID, e);
-
- }
- }
-
- /**
- * Extract Boolean value from JSON
- *
- * @param input
- * @param keyID
- * @param isRequired
- * @return
- * @throws SLCommandoParserException
- */
- public static boolean getBooleanValue(ObjectNode input, String keyID, boolean isRequired, boolean defaultValue) throws SLCommandoParserException {
- try {
- final JsonNode internal = getAndCheck(input, keyID, isRequired);
-
- if (internal != null)
- return internal.asBoolean();
- else
- return defaultValue;
-
- } catch (final SLCommandoParserException e) {
- throw e;
-
- } catch (final Exception e) {
- throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e);
-
- }
- }
-
- /**
- * Extract JSONObject value from JSON
- *
- * @param input
- * @param keyID
- * @param isRequired
- * @return
- * @throws SLCommandoParserException
- */
- public static JsonNode getJSONObjectValue(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException {
- try {
- final JsonNode internal = getAndCheck(input, keyID, isRequired);
-
- if (internal != null)
- return internal;
- else
- return null;
-
- } catch (final SLCommandoParserException e) {
- throw e;
-
- } catch (final Exception e) {
- throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e);
-
- }
- }
-
- /**
- * Extract a List of String elements from a JSON element
- *
- * @param input
- * @return
- * @throws SLCommandoParserException
- */
- public static List<String> getListOfStringElements(JsonNode input) throws SLCommandoParserException {
- final List<String> result = new ArrayList<String>();
- if (input != null) {
- if (input.isArray()) {
- final Iterator<JsonNode> arrayIterator = input.iterator();
- while(arrayIterator.hasNext()) {
- final JsonNode next = arrayIterator.next();
- if (next.isTextual())
- result.add(next.asText());
- }
-
- } else if (input.isTextual()) {
- result.add(input.asText());
-
- } else {
- log.warn("JSON Element IS NOT a JSON array or a JSON Primitive");
- throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive");
-
- }
- }
-
- return result;
- }
-
- /**
- * Extract Map of Key/Value pairs from a JSON Element
- *
- * @param input parent JSON object
- * @param keyID KeyId of the child that should be parsed
- * @param isRequired
- * @return
- * @throws SLCommandoParserException
- */
- public static Map<String, String> getMapOfStringElements(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException {
- final JsonNode internal = getAndCheck(input, keyID, isRequired);
- return getMapOfStringElements(internal);
-
- }
-
- /**
- * Extract Map of Key/Value pairs from a JSON Element
- *
- * @param input
- * @return
- * @throws SLCommandoParserException
- */
- public static Map<String, String> getMapOfStringElements(JsonNode input) throws SLCommandoParserException {
- final Map<String, String> result = new HashMap<String, String>();
-
- if (input != null) {
- if (input.isArray()) {
- final Iterator<JsonNode> arrayIterator = input.iterator();
- while(arrayIterator.hasNext()) {
- final JsonNode next = arrayIterator.next();
- final Iterator<Entry<String, JsonNode>> entry = next.fields();
- entitySetToMap(result, entry);
-
- }
-
- } else if (input.isObject()) {
- final Iterator<Entry<String, JsonNode>> objectKeys = input.fields();
- entitySetToMap(result, objectKeys);
-
- } else
- throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON object");
-
- }
-
- return result;
- }
-
- private static void entitySetToMap(Map<String, String> result, Iterator<Entry<String, JsonNode>> entry) {
- while (entry.hasNext()) {
- final Entry<String, JsonNode> el = entry.next();
- if (result.containsKey(el.getKey()))
- log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... ");
-
- result.put(el.getKey(), el.getValue().asText());
-
- }
-
- }
-
-
- public static JsonNode extractSL20Result(JsonNode command, IJOSETools decrypter, boolean mustBeEncrypted) throws SL20Exception {
- final JsonNode result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT);
- final JsonNode encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT);
-
- if (result == null && encryptedResult == null)
- throw new SLCommandoParserException("NO result OR encryptedResult FOUND.");
-
- else if (encryptedResult == null && mustBeEncrypted)
- throw new SLCommandoParserException("result MUST be encrypted.");
-
- else if (encryptedResult != null && encryptedResult.isTextual()) {
- try {
- return decrypter.decryptPayload(encryptedResult.asText());
-
- } catch (final Exception e) {
- log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage());
- if (!mustBeEncrypted) {
- log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible");
-
- //dummy code
- try {
- final String[] signedPayload = encryptedResult.toString().split("\\.");
- final JsonNode payLoad = mapper.getMapper().readTree(new String(Base64.getUrlDecoder().decode(signedPayload[1])));
- return payLoad;
-
- } catch (final Exception e1) {
- log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ...");
- throw new SL20Exception(e.getMessage(), null, e);
-
- }
-
- } else
- throw e;
-
- }
-
- } else if (result != null) {
- return result;
-
- } else
- throw new SLCommandoParserException("Internal build error");
-
-
- }
-
- /**
- * Extract payLoad from generic transport container
- *
- * @param container
- * @param joseTools
- * @return
- * @throws SLCommandoParserException
- */
- public static VerificationResult extractSL20PayLoad(JsonNode container, IJOSETools joseTools, boolean mustBeSigned) throws SL20Exception {
-
- final JsonNode sl20Payload = container.get(SL20Constants.SL20_PAYLOAD);
- final JsonNode sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD);
-
- if (mustBeSigned && joseTools == null)
- throw new SLCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'");
-
- if (sl20Payload == null && sl20SignedPayload == null)
- throw new SLCommandoParserException("NO payLoad OR signedPayload FOUND.");
-
- else if (sl20SignedPayload == null && mustBeSigned)
- throw new SLCommandoParserException("payLoad MUST be signed.");
-
- else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isTextual()) {
- return joseTools.validateSignature(sl20SignedPayload.asText());
-
- } else if (sl20Payload != null)
- return new VerificationResult(sl20Payload);
-
- else
- throw new SLCommandoParserException("Internal build error");
-
-
- }
-
-
- /**
- * Extract generic transport container from httpResponse
- *
- * @param httpResp
- * @return
- * @throws SLCommandoParserException
- */
- public static JsonNode getSL20ContainerFromResponse(HttpResponse httpResp) throws SLCommandoParserException {
- try {
- JsonNode sl20Resp = null;
- if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) {
- final Header[] locationHeader = httpResp.getHeaders("Location");
- if (locationHeader == null)
- throw new SLCommandoParserException("Find Redirect statuscode but not Location header");
-
- final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue();
- sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString));
-
- } else if (httpResp.getStatusLine().getStatusCode() == 200) {
- if (httpResp.getEntity().getContentType() == null)
- throw new SLCommandoParserException("SL20 response contains NO ContentType");
-
- if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json"))
- throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue());
- sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
-
- } else if ( (httpResp.getStatusLine().getStatusCode() == 500) ||
- (httpResp.getStatusLine().getStatusCode() == 401) ||
- (httpResp.getStatusLine().getStatusCode() == 400) ) {
- log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()
- + ". Search for error message");
-
- try {
- sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
-
- } catch (final Exception e) {
- log.warn("SL20 response contains no valid JSON", e);
- throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()
- + " AND NO valid JSON errormsg", e);
-
- }
-
-
-
- } else
- throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode());
-
- log.info("Find JSON object in http response");
- return sl20Resp;
-
- } catch (final Exception e) {
- throw new SLCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e);
-
- }
- }
-
- private static JsonNode parseSL20ResultFromResponse(HttpEntity resp) throws Exception {
- if (resp != null && resp.getContent() != null) {
- final String rawSL20Resp = EntityUtils.toString(resp);
- final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp);
-
- //TODO: check sl20Resp type like && sl20Resp.isJsonObject()
- if (sl20Resp != null) {
- return sl20Resp;
-
- } else
- throw new SLCommandoParserException("SL2.0 can NOT parse to a JSON object");
-
-
- } else
- throw new SLCommandoParserException("Can NOT find content in http response");
-
- }
-
-
- private static JsonNode getAndCheck(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException {
- final JsonNode internal = input.get(keyID);
-
- if (internal == null && isRequired)
- throw new SLCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist");
-
- return internal;
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java
new file mode 100644
index 00000000..eb17781b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java
@@ -0,0 +1,677 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException;
+
+public class SL20JsonBuilderUtils {
+
+ private static JsonMapper mapper = new JsonMapper();
+
+ /**
+ * Create command request.
+ *
+ * @param name Commando name
+ * @param params Commando parameters
+ * @return JSON Object
+ * @throws SlCommandoBuildException In case of a build error
+ */
+ public static ObjectNode createCommand(final String name, final ObjectNode params) throws SlCommandoBuildException {
+
+ final ObjectNode command = mapper.getMapper().createObjectNode();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addSingleJsonElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);
+ return command;
+
+ }
+
+ /**
+ * Create signed command request.
+ *
+ * @param name Commando name
+ * @param params commando parameter
+ * @param signer JWS signer implementation
+ * @return Serialized JWS
+ * @throws SlCommandoBuildException In case of a build error
+ */
+ public static String createSignedCommand(final String name, final ObjectNode params, final IJoseTools signer)
+ throws SlCommandoBuildException {
+ final ObjectNode command = mapper.getMapper().createObjectNode();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addSingleJsonElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);
+ return signer.createSignature(command.toString());
+
+ }
+
+ /**
+ * Create encrypted command result.
+ *
+ * @param result JSON to encrypt
+ * @param encrypter JWE encrypter implementation
+ * @return Serialized JWE
+ * @throws SlCommandoBuildException In case of a processing error
+ */
+ public static String createEncryptedCommandoResult(final ObjectNode result, final JsonSecurityUtils encrypter)
+ throws SlCommandoBuildException {
+ // TODO: add real implementation
+ // create header and footer
+ final String dummyHeader = createJsonEncryptionHeader().toString();
+ final String payLoad = result.toString();
+ final String dummyFooter = createJsonSignedFooter();
+
+ try {
+ return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes("UTF-8")) + "."
+ + Base64.getUrlEncoder().encodeToString(payLoad.getBytes("UTF-8")) + "."
+ + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes("UTF-8"));
+ } catch (final UnsupportedEncodingException e) {
+ throw new SlCommandoBuildException("No UTF-8 encoding", e);
+ }
+
+ }
+
+ /**
+ * Create command result.
+ *
+ * @param name Commando name
+ * @param result commande result
+ * @param encryptedResult encrypted commando result
+ * @return Result json
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createCommandResponse(final String name, final ObjectNode result,
+ final String encryptedResult) throws SlCommandoBuildException {
+ final ObjectNode command = mapper.getMapper().createObjectNode();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT,
+ SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult);
+ return command;
+
+ }
+
+ /**
+ * Create signed command result.
+ *
+ * @param name commando name
+ * @param result commando result
+ * @param encryptedResult encrypted commando result
+ * @return JWS in serialized form
+ * @throws SlCommandoBuildException in case of an error
+ *
+ */
+ public static String createSignedCommandResponse(final String name, final ObjectNode result,
+ final String encryptedResult, final JsonSecurityUtils signer) throws SlCommandoBuildException {
+ final ObjectNode command = mapper.getMapper().createObjectNode();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT,
+ SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult);
+ final String encodedCommand = command.toString();
+
+ // TODO: add real implementation
+ // create header and footer
+ final String dummyHeader = createJsonSignedHeader().toString();
+ final String dummyFooter = createJsonSignedFooter();
+
+ try {
+ return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes("UTF-8")) + "."
+ + Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes("UTF-8")) + "."
+ + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes("UTF-8"));
+
+ } catch (final UnsupportedEncodingException e) {
+ throw new SlCommandoBuildException("No UTF-8 encoding", e);
+ }
+
+ }
+
+ /**
+ * Create parameters for Redirect command.
+ *
+ * @param url redirect URL
+ * @param command embedded command
+ * @param signedCommand Signed embedded command
+ * @param ipcRedirect IPC redirect flag
+ * @return result JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createRedirectCommandParameters(final String url, final ObjectNode command,
+ final ObjectNode signedCommand, final Boolean ipcRedirect) throws SlCommandoBuildException {
+ final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode();
+ addOnlyOnceOfTwo(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, command, signedCommand);
+ addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false);
+ addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT,
+ ipcRedirect, false);
+ return redirectReqParams;
+
+ }
+
+ /**
+ * Create parameters for Call command.
+ *
+ * @param url http URL for Call command
+ * @param method http method used by call commando result
+ * @param includeTransactionId TransactionId
+ * @param reqParameters Request parameters on CALL command
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createCallCommandParameters(final String url, final String method,
+ final Boolean includeTransactionId, final Map<String, String> reqParameters) throws SlCommandoBuildException {
+ final ObjectNode callReqParams = mapper.getMapper().createObjectNode();
+ addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true);
+ addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true);
+ addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID,
+ includeTransactionId, false);
+ addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters);
+ return callReqParams;
+
+ }
+
+ /**
+ * Create result for Error command.
+ *
+ * @param errorCode Error-Code
+ * @param errorMsg Error-message
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createErrorCommandResult(final String errorCode, final String errorMsg)
+ throws SlCommandoBuildException {
+ final ObjectNode result = mapper.getMapper().createObjectNode();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true);
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true);
+ return result;
+
+ }
+
+ /**
+ * Create parameters for qualifiedeID command.
+ *
+ * @param consentTemplateId Identifier of the template that is used for consent
+ * visualization
+ * @param consent Consent that has to be signed by user
+ * @param dataUrl DataURL for result
+ * @param x5cEnc Response encryption certificate
+ * @return JSON
+ * @throws CertificateEncodingException In case of a encryption certificate
+ * encoding problem
+ * @throws SlCommandoBuildException In case of a generel error
+ */
+ public static ObjectNode createQualifiedeEidConsent(final String consentTemplateId, final byte[] consent,
+ final String dataUrl, final X509Certificate x5cEnc)
+ throws CertificateEncodingException, SlCommandoBuildException {
+ final ObjectNode params = mapper.getMapper().createObjectNode();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true);
+ addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create parameters for qualifiedeID command.
+ *
+ * @param authBlockId AuthBlock transformation Id
+ * @param dataUrl DataURL for result
+ * @param additionalReqParameters additional parameters
+ * @param x5cEnc Response encryption certificate
+ * @return JSON
+ * @throws CertificateEncodingException In case of a encryption certificate
+ * encoding problem
+ * @throws SlCommandoBuildException In case of a generel error
+ */
+ @Deprecated
+ public static ObjectNode createQualifiedEidCommandParameters(final String authBlockId, final String dataUrl,
+ final Map<String, String> additionalReqParameters, final X509Certificate x5cEnc)
+ throws CertificateEncodingException, SlCommandoBuildException {
+ final ObjectNode params = mapper.getMapper().createObjectNode();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true);
+ addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create result for qualifiedeID command.
+ *
+ * @param idl IdentityLink
+ * @param authBlock AuthBlock
+ * @param ccsUrl VDA URL
+ * @param loa LoA
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createQualifiedEidCommandResult(final byte[] idl, final byte[] authBlock,
+ final String ccsUrl, final String loa) throws SlCommandoBuildException {
+ final ObjectNode result = mapper.getMapper().createObjectNode();
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true);
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsUrl, true);
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, loa, true);
+ return result;
+
+ }
+
+ /**
+ * Create Binding-Key command parameters.
+ *
+ * @param kontoId KontoId
+ * @param subjectName SubjectName
+ * @param keySize KeySize
+ * @param keyAlg Key-algorithm
+ * @param policies Key policy
+ * @param dataUrl DataURL
+ * @param x5cVdaTrust trusted certificate from VDA
+ * @param reqUserPassword User passwort initialize request
+ * @param x5cEnc Result encryption certificate
+ * @return JSON
+ * @throws SlCommandoBuildException in case of an errr
+ * @throws CertificateEncodingException In case of a certificate error
+ */
+ public static ObjectNode createBindingKeyCommandParams(final String kontoId, final String subjectName,
+ final int keySize, final String keyAlg, final Map<String, String> policies, final String dataUrl,
+ final X509Certificate x5cVdaTrust, final Boolean reqUserPassword, final X509Certificate x5cEnc)
+ throws SlCommandoBuildException, CertificateEncodingException {
+ final ObjectNode params = mapper.getMapper().createObjectNode();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true);
+ addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true);
+ addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust,
+ false);
+ addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD,
+ reqUserPassword, false);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create Binding-Key command result.
+ *
+ * @param appId AppId
+ * @param csr CSR
+ * @param attCert Key-Attestation certificate
+ * @param password user's password
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ * @throws CertificateEncodingException In case of a certificate processing
+ * error
+ */
+ public static ObjectNode createBindingKeyCommandResult(final String appId, final byte[] csr,
+ final X509Certificate attCert, final byte[] password)
+ throws SlCommandoBuildException, CertificateEncodingException {
+ final ObjectNode result = mapper.getMapper().createObjectNode();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true);
+ addSingleCertificateElement(result,
+ SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false);
+ return result;
+
+ }
+
+ /**
+ * Create Store Binding-Certificate command parameters.
+ *
+ * @param cert Certificate
+ * @param dataUrl DATA URL
+ * @return JSON
+ * @throws CertificateEncodingException In case of a certificate processing
+ * error
+ * @throws SlCommandoBuildException In case of a error
+ */
+ public static ObjectNode createStoreBindingCertCommandParams(final X509Certificate cert, final String dataUrl)
+ throws CertificateEncodingException, SlCommandoBuildException {
+ final ObjectNode params = mapper.getMapper().createObjectNode();
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true);
+ return params;
+
+ }
+
+ /**
+ * Create Store Binding-Certificate command result.
+ *
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SlCommandoBuildException {
+ final ObjectNode result = mapper.getMapper().createObjectNode();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS,
+ SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true);
+ return result;
+
+ }
+
+ /**
+ * Create idAndPassword command parameters.
+ *
+ * @param keyAlg key algorithm
+ * @param dataUrl DATA Url
+ * @param x5cEnc result encryption certificate
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ * @throws CertificateEncodingException In case of a certificate processing
+ * error
+ */
+ public static ObjectNode createIdAndPasswordCommandParameters(final String keyAlg, final String dataUrl,
+ final X509Certificate x5cEnc) throws SlCommandoBuildException, CertificateEncodingException {
+ final ObjectNode params = mapper.getMapper().createObjectNode();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create idAndPassword command result.
+ *
+ * @param kontoId User's Id
+ * @param password User's password
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createIdAndPasswordCommandResult(final String kontoId, final byte[] password)
+ throws SlCommandoBuildException {
+ final ObjectNode result = mapper.getMapper().createObjectNode();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password,
+ true);
+ return result;
+
+ }
+
+ /**
+ * Create JWS Token Authentication command.
+ *
+ * @param nonce nonce that should be signed
+ * @param dataUrl Data URL
+ * @param displayData Data that should be displayed
+ * @param displayUrl URL to data that should be displayed
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createJwsTokenAuthCommandParams(final String nonce, final String dataUrl,
+ final List<String> displayData, final List<String> displayUrl) throws SlCommandoBuildException {
+ final ObjectNode params = mapper.getMapper().createObjectNode();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true);
+ addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData);
+ addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl);
+ return params;
+
+ }
+
+ /**
+ * Create JWS Token Authentication command result.
+ *
+ * @param nonce Serialzed JWS that contains the signed nonce
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createJwsTokenAuthCommandResult(final String nonce) throws SlCommandoBuildException {
+ final ObjectNode result = mapper.getMapper().createObjectNode();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true);
+ return result;
+
+ }
+
+ /**
+ * Create Generic Request Container.
+ *
+ * @param reqId RequestId
+ * @param transactionId TransactionId
+ * @param payLoad unsigned payload
+ * @param signedPayload Signed payload
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static ObjectNode createGenericRequest(final String reqId, final String transactionId,
+ final ObjectNode payLoad, final String signedPayload) throws SlCommandoBuildException {
+ final ObjectNode req = mapper.getMapper().createObjectNode();
+ addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);
+ addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true);
+ addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);
+ addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, signedPayload);
+ return req;
+
+ }
+
+ /**
+ * Create Generic Response Container.
+ *
+ * @param respId Response Id
+ * @param inResponseTo RequestId to this response
+ * @param transactionId transactionId
+ * @param payLoad Unsigned payload
+ * @param signedPayload Signed payload
+ * @return JSON
+ * @throws SlCommandoBuildException In case of an error
+ */
+ public static final ObjectNode createGenericResponse(final String respId, final String inResponseTo,
+ final String transactionId, final ObjectNode payLoad, final String signedPayload)
+ throws SlCommandoBuildException {
+ final ObjectNode req = mapper.getMapper().createObjectNode();
+ addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);
+ addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true);
+ addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false);
+ addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);
+ addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, signedPayload);
+ return req;
+
+ }
+
+ private static void addOnlyOnceOfTwo(final ObjectNode parent, final String firstKeyId, final String secondKeyId,
+ final ObjectNode first, final ObjectNode second) throws SlCommandoBuildException {
+ if (first == null && second == null) {
+ throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL");
+ } else if (first != null && second != null) {
+ throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE");
+ } else if (first != null) {
+ parent.set(firstKeyId, first);
+ } else if (second != null) {
+ parent.set(secondKeyId, second);
+ } else {
+ throw new SlCommandoBuildException("Internal build error");
+ }
+ }
+
+ /**
+ * Add one element of two possible elements <br>
+ * This method adds either the first element or the second element to parent
+ * JSON, but never both.
+ *
+ * @param parent Parent JSON element
+ * @param firstKeyId first element Id
+ * @param secondKeyId second element Id
+ * @param first first element
+ * @param second second element
+ * @throws SlCommandoBuildException In case of an error.
+ */
+ public static void addOnlyOnceOfTwo(final ObjectNode parent, final String firstKeyId, final String secondKeyId,
+ final ObjectNode first, final String second) throws SlCommandoBuildException {
+ if (first == null && (second == null || second.isEmpty())) {
+ throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL");
+ } else if (first != null && second != null) {
+ throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE");
+ } else if (first != null) {
+ parent.set(firstKeyId, first);
+ } else if (second != null && !second.isEmpty()) {
+ parent.put(secondKeyId, second);
+ } else {
+ throw new SlCommandoBuildException("Internal build error");
+ }
+ }
+
+ // TODO!!!!
+ private static ObjectNode createJsonSignedHeader() throws SlCommandoBuildException {
+ final ObjectNode header = mapper.getMapper().createObjectNode();
+ addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true);
+ addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true);
+ addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT));
+
+ return header;
+ }
+
+ // TODO!!!!
+ private static ObjectNode createJsonEncryptionHeader() throws SlCommandoBuildException {
+ final ObjectNode header = mapper.getMapper().createObjectNode();
+ addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true);
+ addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD,
+ SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true);
+ addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT,
+ true);
+ addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true);
+
+ return header;
+ }
+
+ // TODO!!!!
+ private static String createJsonSignedFooter() {
+ return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n"
+ + " AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n"
+ + " BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n"
+ + " 0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n"
+ + " hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" + " p0igcN_IoypGlUPQGe77Rw";
+ }
+
+ private static void addArrayOfStrings(final ObjectNode parent, final String keyId, final List<String> values)
+ throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+ if (values != null) {
+ final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode();
+ parent.set(keyId, callReqParamsArray);
+ for (final String el : values) {
+ callReqParamsArray.add(el);
+ }
+
+ }
+ }
+
+ private static void addArrayOfStringElements(final ObjectNode parent, final String keyId,
+ final Map<String, String> keyValuePairs) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+ if (keyValuePairs != null) {
+ final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode();
+ parent.set(keyId, callReqParamsArray);
+
+ for (final Entry<String, String> el : keyValuePairs.entrySet()) {
+ final ObjectNode callReqParams = mapper.getMapper().createObjectNode();
+ callReqParams.put(el.getKey(), el.getValue());
+ callReqParamsArray.add(callReqParams);
+
+ }
+ }
+ }
+
+ private static void addSingleCertificateElement(final ObjectNode parent, final String keyId,
+ final X509Certificate cert, final boolean isRequired)
+ throws CertificateEncodingException, SlCommandoBuildException {
+ if (cert != null) {
+ addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired);
+ } else if (isRequired) {
+ throw new SlCommandoBuildException(keyId + " is marked as REQUIRED");
+ }
+
+ }
+
+ private static void addSingleByteElement(final ObjectNode parent, final String keyId, final byte[] value,
+ final boolean isRequired) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ throw new SlCommandoBuildException(keyId + " has NULL value");
+ } else if (value != null) {
+ parent.put(keyId, Base64.getEncoder().encodeToString(value));
+ }
+
+ }
+
+ private static void addSingleBooleanElement(final ObjectNode parent, final String keyId, final Boolean value,
+ final boolean isRequired) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ throw new SlCommandoBuildException(keyId + " has a NULL value");
+ } else if (value != null) {
+ parent.put(keyId, value);
+ }
+
+ }
+
+ private static void addSingleNumberElement(final ObjectNode parent, final String keyId, final Integer value,
+ final boolean isRequired) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ throw new SlCommandoBuildException(keyId + " has a NULL value");
+ } else if (value != null) {
+ parent.put(keyId, value);
+ }
+
+ }
+
+ private static void addSingleStringElement(final ObjectNode parent, final String keyId, final String value,
+ final boolean isRequired) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && (value == null || value.isEmpty())) {
+ throw new SlCommandoBuildException(keyId + " has an empty value");
+ } else if (value != null && !value.isEmpty()) {
+ parent.put(keyId, value);
+ }
+
+ }
+
+ private static void addSingleIntegerElement(final ObjectNode parent, final String keyId, final Integer value,
+ final boolean isRequired) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ throw new SlCommandoBuildException(keyId + " has an empty value");
+ } else if (value != null) {
+ parent.put(keyId, value);
+ }
+
+ }
+
+ private static void addSingleJsonElement(final ObjectNode parent, final String keyId, final ObjectNode element,
+ final boolean isRequired) throws SlCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && element == null) {
+ throw new SlCommandoBuildException("No commando name included");
+ } else if (element != null) {
+ parent.set(keyId, element);
+ }
+
+ }
+
+ private static void validateParentAndKey(final ObjectNode parent, final String keyId)
+ throws SlCommandoBuildException {
+ if (parent == null) {
+ throw new SlCommandoBuildException("NO parent JSON element");
+ }
+
+ if (keyId == null || keyId.isEmpty()) {
+ throw new SlCommandoBuildException("NO JSON element identifier");
+ }
+ }
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java
new file mode 100644
index 00000000..eb6de461
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java
@@ -0,0 +1,389 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.utils;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.util.EntityUtils;
+import org.jose4j.base64url.Base64Url;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;
+
+public class SL20JsonExtractorUtils {
+ private static final Logger log = LoggerFactory.getLogger(SL20JsonExtractorUtils.class);
+ private static JsonMapper mapper = new JsonMapper();
+
+ /**
+ * Extract String value from JSON.
+ *
+ * @param input JSON
+ * @param keyID Element identifier
+ * @param isRequired true, if the element must not null
+ * @return Value of this element
+ * @throws SlCommandoParserException In case an error
+ */
+ public static String getStringValue(final JsonNode input, final String keyID, final boolean isRequired)
+ throws SlCommandoParserException {
+ try {
+ final JsonNode internal = getAndCheck(input, keyID, isRequired);
+
+ if (internal != null) {
+ return internal.asText();
+ } else {
+ return null;
+ }
+
+ } catch (final SlCommandoParserException e) {
+ throw e;
+
+ } catch (final Exception e) {
+ throw new SlCommandoParserException("Can not extract String value with keyId: " + keyID, e);
+
+ }
+ }
+
+ /**
+ * Extract Boolean value from JSON.
+ *
+ * @param input JSON
+ * @param keyID Element identifier
+ * @param isRequired true, if the element must not null
+ * @return Boolean
+ * @throws SlCommandoParserException In case of an error
+ */
+ public static boolean getBooleanValue(final ObjectNode input, final String keyID, final boolean isRequired,
+ final boolean defaultValue) throws SlCommandoParserException {
+ try {
+ final JsonNode internal = getAndCheck(input, keyID, isRequired);
+
+ if (internal != null) {
+ return internal.asBoolean();
+ } else {
+ return defaultValue;
+ }
+
+ } catch (final SlCommandoParserException e) {
+ throw e;
+
+ } catch (final Exception e) {
+ throw new SlCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e);
+
+ }
+ }
+
+ /**
+ * Extract JSONObject value from JSON.
+ *
+ * @param input JSON
+ * @param keyID Element identifier
+ * @param isRequired true, if the element must not null
+ * @return JSON node
+ * @throws SlCommandoParserException In case of an error
+ */
+ public static JsonNode getJsonObjectValue(final JsonNode input, final String keyID, final boolean isRequired)
+ throws SlCommandoParserException {
+ try {
+ final JsonNode internal = getAndCheck(input, keyID, isRequired);
+
+ if (internal != null) {
+ return internal;
+ } else {
+ return null;
+ }
+
+ } catch (final SlCommandoParserException e) {
+ throw e;
+
+ } catch (final Exception e) {
+ throw new SlCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e);
+
+ }
+ }
+
+ /**
+ * Extract a List of String elements from a JSON element.
+ *
+ * @param input JSON
+ * @return List of Elements in this node
+ * @throws SlCommandoParserException In case of an error
+ */
+ public static List<String> getListOfStringElements(final JsonNode input) throws SlCommandoParserException {
+ final List<String> result = new ArrayList<>();
+ if (input != null) {
+ if (input.isArray()) {
+ final Iterator<JsonNode> arrayIterator = input.iterator();
+ while (arrayIterator.hasNext()) {
+ final JsonNode next = arrayIterator.next();
+ if (next.isTextual()) {
+ result.add(next.asText());
+ }
+ }
+
+ } else if (input.isTextual()) {
+ result.add(input.asText());
+
+ } else {
+ log.warn("JSON Element IS NOT a JSON array or a JSON Primitive");
+ throw new SlCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive");
+
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Extract Map of Key/Value pairs from a JSON Element.
+ *
+ * @param input parent JSON object
+ * @param keyID KeyId of the child that should be parsed
+ * @param isRequired true, if the element must not null
+ * @return Map of element pairs
+ * @throws SlCommandoParserException In case of an error
+ */
+ public static Map<String, String> getMapOfStringElements(final JsonNode input, final String keyID,
+ final boolean isRequired) throws SlCommandoParserException {
+ final JsonNode internal = getAndCheck(input, keyID, isRequired);
+ return getMapOfStringElements(internal);
+
+ }
+
+ /**
+ * Extract Map of Key/Value pairs from a JSON Element.
+ *
+ * @param input JSON
+ * @return Map of element pairs
+ * @throws SlCommandoParserException in case of an error
+ */
+ public static Map<String, String> getMapOfStringElements(final JsonNode input) throws SlCommandoParserException {
+ final Map<String, String> result = new HashMap<>();
+
+ if (input != null) {
+ if (input.isArray()) {
+ final Iterator<JsonNode> arrayIterator = input.iterator();
+ while (arrayIterator.hasNext()) {
+ final JsonNode next = arrayIterator.next();
+ final Iterator<Entry<String, JsonNode>> entry = next.fields();
+ entitySetToMap(result, entry);
+
+ }
+
+ } else if (input.isObject()) {
+ final Iterator<Entry<String, JsonNode>> objectKeys = input.fields();
+ entitySetToMap(result, objectKeys);
+
+ } else {
+ throw new SlCommandoParserException("JSON Element IS NOT a JSON array or a JSON object");
+ }
+
+ }
+
+ return result;
+ }
+
+ private static void entitySetToMap(final Map<String, String> result, final Iterator<Entry<String, JsonNode>> entry) {
+ while (entry.hasNext()) {
+ final Entry<String, JsonNode> el = entry.next();
+ if (result.containsKey(el.getKey())) {
+ log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... ");
+ }
+
+ result.put(el.getKey(), el.getValue().asText());
+
+ }
+
+ }
+
+ /**
+ * Extract Security-Layer 2.0 result from response object.
+ *
+ * @param command SL2.0 command
+ * @param decrypter JWS decrypter implementation
+ * @param mustBeEncrypted if <code>true</code>, the result must be encrypted
+ * @return decrypted JSON
+ * @throws SL20Exception In case of an error
+ */
+ public static JsonNode extractSL20Result(final JsonNode command, final IJoseTools decrypter,
+ final boolean mustBeEncrypted) throws SL20Exception {
+ final JsonNode result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT);
+ final JsonNode encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT);
+
+ if (result == null && encryptedResult == null) {
+ throw new SlCommandoParserException("NO result OR encryptedResult FOUND.");
+ } else if (encryptedResult == null && mustBeEncrypted) {
+ throw new SlCommandoParserException("result MUST be encrypted.");
+ } else if (encryptedResult != null && encryptedResult.isTextual()) {
+ try {
+ return decrypter.decryptPayload(encryptedResult.asText());
+
+ } catch (final Exception e) {
+ log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage());
+ if (!mustBeEncrypted) {
+ log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible");
+
+ // dummy code
+ try {
+ final String[] signedPayload = encryptedResult.toString().split("\\.");
+ final JsonNode payLoad = mapper.getMapper()
+ .readTree(new String(Base64.getUrlDecoder().decode(signedPayload[1]), "UTF-8"));
+ return payLoad;
+
+ } catch (final Exception e1) {
+ log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ...");
+ throw new SL20Exception(e.getMessage(), null, e);
+
+ }
+
+ } else {
+ throw e;
+ }
+
+ }
+
+ } else if (result != null) {
+ return result;
+
+ } else {
+ throw new SlCommandoParserException("Internal build error");
+ }
+
+ }
+
+ /**
+ * Extract payLoad from generic transport container.
+ *
+ * @param container JSON
+ * @param joseTools JWS implementation
+ * @return Signature verification result that contains the payLoad
+ * @throws SlCommandoParserException In case of an error
+ */
+ public static VerificationResult extractSL20PayLoad(final JsonNode container, final IJoseTools joseTools,
+ final boolean mustBeSigned) throws SL20Exception {
+
+ final JsonNode sl20Payload = container.get(SL20Constants.SL20_PAYLOAD);
+ final JsonNode sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD);
+
+ if (mustBeSigned && joseTools == null) {
+ throw new SlCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'");
+ }
+
+ if (sl20Payload == null && sl20SignedPayload == null) {
+ throw new SlCommandoParserException("NO payLoad OR signedPayload FOUND.");
+ } else if (sl20SignedPayload == null && mustBeSigned) {
+ throw new SlCommandoParserException("payLoad MUST be signed.");
+ } else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isTextual()) {
+ return joseTools.validateSignature(sl20SignedPayload.asText());
+
+ } else if (sl20Payload != null) {
+ return new VerificationResult(sl20Payload);
+ } else {
+ throw new SlCommandoParserException("Internal build error");
+ }
+
+ }
+
+ /**
+ * Extract generic transport container from httpResponse.
+ *
+ * @param httpResp Http response object
+ * @return JSON with SL2.0 response
+ * @throws SlCommandoParserException In case of an error
+ */
+ public static JsonNode getSL20ContainerFromResponse(final HttpResponse httpResp) throws SlCommandoParserException {
+ try {
+ JsonNode sl20Resp = null;
+ if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) {
+ final Header[] locationHeader = httpResp.getHeaders("Location");
+ if (locationHeader == null) {
+ throw new SlCommandoParserException("Find Redirect statuscode but not Location header");
+ }
+
+ final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue();
+ sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString));
+
+ } else if (httpResp.getStatusLine().getStatusCode() == 200) {
+ if (httpResp.getEntity().getContentType() == null) {
+ throw new SlCommandoParserException("SL20 response contains NO ContentType");
+ }
+
+ if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) {
+ throw new SlCommandoParserException(
+ "SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue());
+ }
+ sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
+
+ } else if (httpResp.getStatusLine().getStatusCode() == 500 || httpResp.getStatusLine().getStatusCode() == 401
+ || httpResp.getStatusLine().getStatusCode() == 400) {
+ log.info(
+ "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() + ". Search for error message");
+
+ try {
+ sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
+
+ } catch (final Exception e) {
+ log.warn("SL20 response contains no valid JSON", e);
+ throw new SlCommandoParserException("SL20 response with http-code: "
+ + httpResp.getStatusLine().getStatusCode() + " AND NO valid JSON errormsg", e);
+
+ }
+
+ } else {
+ throw new SlCommandoParserException(
+ "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode());
+ }
+
+ log.info("Find JSON object in http response");
+ return sl20Resp;
+
+ } catch (final Exception e) {
+ throw new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception {
+ if (resp != null && resp.getContent() != null) {
+ final String rawSL20Resp = EntityUtils.toString(resp);
+ final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp);
+
+ // TODO: check sl20Resp type like && sl20Resp.isJsonObject()
+ if (sl20Resp != null) {
+ return sl20Resp;
+
+ } else {
+ throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object");
+ }
+
+ } else {
+ throw new SlCommandoParserException("Can NOT find content in http response");
+ }
+
+ }
+
+ private static JsonNode getAndCheck(final JsonNode input, final String keyID, final boolean isRequired)
+ throws SlCommandoParserException {
+ final JsonNode internal = input.get(keyID);
+
+ if (internal == null && isRequired) {
+ throw new SlCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist");
+ }
+
+ return internal;
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java
new file mode 100644
index 00000000..4bb91634
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java
@@ -0,0 +1,166 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.utils;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.ContentType;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SL20ResponseUtils {
+ private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#";
+
+ /**
+ * Build a generic SL2.x error-response without redirect to AuthHandler.
+ *
+ * @param response http response object
+ * @param errorCode ErrorCode
+ * @param errorMsg Error message
+ * @throws Exception In case of a message generation error
+ */
+ public static void buildErrorResponse(final HttpServletResponse response,
+ final String errorCode, final String errorMsg)
+ throws Exception {
+ final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg);
+ final ObjectNode errorCommand = SL20JsonBuilderUtils
+ .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null);
+
+ final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericResponse(UUID.randomUUID().toString(), null,
+ null, errorCommand, null);
+
+ log.trace("SL20 response to VDA: " + respContainer);
+ final StringWriter writer = new StringWriter();
+ writer.write(respContainer.toString());
+ final byte[] content = writer.toString().getBytes("UTF-8");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentLength(content.length);
+ response.setContentType(ContentType.APPLICATION_JSON.toString());
+ response.getOutputStream().write(content);
+
+ }
+
+ /**
+ * Build a Security-Layer 2.x conform redirect response.
+ *
+ * @param request http request
+ * @param response http response
+ * @param pendingReq Current pending request
+ * @param fullRedirectUrl Endpoint, where the auth. process should be resumed after redirect
+ * @param transactionId SL2.0 transactionId if available
+ * @param authConfig Basic application configuration
+ * @throws IOException In case of a http servlet error
+ * @throws SL20Exception In case of a SL2.0 request generation error
+ * @throws URISyntaxException In case of an invalid Redirect URL
+ */
+ public static void buildResponse(final HttpServletRequest request, final HttpServletResponse response,
+ IRequest pendingReq, String fullRedirectUrl, String transactionId, IConfiguration authConfig)
+ throws IOException, SL20Exception, URISyntaxException {
+ // create response
+ final Map<String, String> reqParameters = new HashMap<>();
+
+ final URL redirectUrl = new URL(fullRedirectUrl);
+ if (redirectUrl.getQuery() != null) {
+ final String [] elements = redirectUrl.getQuery().split("&");
+ for (final String element : elements) {
+ final String[] keyValue = element.split("=");
+ if (keyValue.length == 2) {
+ reqParameters.put(keyValue[0], keyValue[1]);
+
+ } else {
+ log.warn("Ignore parameter with name: {}", keyValue[0]);
+
+ }
+ }
+ }
+
+ //reqParameters.put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId());
+
+ final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters(
+ fullRedirectUrl.split("\\?")[0],
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters);
+ final ObjectNode callCommand = SL20JsonBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL,
+ callReqParams);
+
+ // build first redirect command for app
+ final ObjectNode redirectOneParams = SL20JsonBuilderUtils
+ .createRedirectCommandParameters(generateIpcRedirectUrlForDebugging(
+ pendingReq,
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL)),
+ callCommand, null, true);
+ final ObjectNode redirectOneCommand = SL20JsonBuilderUtils
+ .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams);
+
+ // build second redirect command for IDP
+ final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters(
+ fullRedirectUrl,
+ redirectOneCommand, null, false);
+ final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils
+ .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams);
+
+ // build generic SL2.0 response container
+ final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest(UUID.randomUUID().toString(),
+ transactionId, redirectTwoCommand, null);
+
+ if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request
+ .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
+ log.debug("Client request containts 'native client' header ... ");
+ log.trace("SL20 response to VDA: " + respContainer);
+ final StringWriter writer = new StringWriter();
+ writer.write(respContainer.toString());
+ final byte[] content = writer.toString().getBytes("UTF-8");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentLength(content.length);
+ response.setContentType(ContentType.APPLICATION_JSON.toString());
+ response.getOutputStream().write(content);
+
+ } else {
+ log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'");
+
+ log.debug("Client request containts is no native client ... ");
+ final URIBuilder clientRedirectUri = new URIBuilder(fullRedirectUrl);
+ response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,
+ Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));
+ response.setHeader("Location", clientRedirectUri.build().toString());
+
+ }
+ }
+
+ /**
+ * Generates a IPC redirect URL that is configured on IDP side.
+ *
+ * @return IPC ReturnURL, or null if no URL is configured
+ */
+ private static String generateIpcRedirectUrlForDebugging(IRequest pendingReq, String ipcRedirectUrlConfig) {
+ if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) {
+ if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) {
+ log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... ");
+ ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#",
+ EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId());
+
+ }
+
+ return ipcRedirectUrlConfig;
+ }
+
+ return null;
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/pom.xml b/eaaf_modules/eaaf_module_moa-sig/pom.xml
index 7911d2cb..11b8cfd9 100644
--- a/eaaf_modules/eaaf_module_moa-sig/pom.xml
+++ b/eaaf_modules/eaaf_module_moa-sig/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>at.gv.egiz.eaaf</groupId>
<artifactId>eaaf_modules</artifactId>
- <version>1.0.13.2</version>
+ <version>1.1.0</version>
</parent>
<artifactId>eaaf_module_moa-sig</artifactId>
<name>MOA-Sig signature verification module</name>
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java
index a3243635..67e9e29d 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java
@@ -2,83 +2,99 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api;
import java.util.List;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICmsSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException;
public interface ISignatureVerificationService {
- /**
- * Verify a CAdES or CMS signature
- * <br><br>
- * <i>This method only validates the first CMS or CAdES signature if more than one signature exists</i>
- *
- * @param signature Enveloped CMS or CAdES signature
- * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
- * @return @link {@link ICMSSignatureVerificationResponse}, or null if no signature was found
- * @throws MOASigServiceException on signatue-verification error
- */
- ICMSSignatureVerificationResponse verifyCMSSignature(byte[] signature, String trustProfileID)
- throws MOASigServiceException;
+ /**
+ * Verify a CAdES or CMS signature. <br>
+ * <br>
+ * <i>This method only validates the first CMS or CAdES signature if more than
+ * one signature exists</i>
+ *
+ * @param signature Enveloped CMS or CAdES signature
+ * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
+ * @return @link {@link ICmsSignatureVerificationResponse}, or null if no
+ * signature was found
+ * @throws MoaSigServiceException on signatue-verification error
+ */
+ ICmsSignatureVerificationResponse verifyCmsSignature(byte[] signature, String trustProfileID)
+ throws MoaSigServiceException;
+ /**
+ * Verify a XML or XAdES signature. <br>
+ * <br>
+ * <i>This method only validates the first XML or XAdES signature if more than
+ * one signature exists</i>
+ *
+ * @param signature Serialized XML or XAdES signature
+ * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
+ * @return @link {@link IXmlSignatureVerificationResponse}, or null if no
+ * signature was found
+ * @throws MoaSigServiceException on signatue-verification error
+ */
+ IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID)
+ throws MoaSigServiceException;
+ /**
+ * Verify a XML or XAdES signature. <br>
+ * <br>
+ * <i>This method only validates the first XML or XAdES signature if more than
+ * one signature exists</i>
+ *
+ * @param signature Serialized XML or XAdES signature
+ * @param trustProfileID Id of the Trust-Profile from MOA-Sig
+ * configuration
+ * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that
+ * should be used for
+ * signature-verification
+ * @return @link {@link IXmlSignatureVerificationResponse}, or null if no
+ * signature was found
+ * @throws MoaSigServiceException on signatue-verification error
+ */
+ IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID,
+ List<String> verifyTransformsInfoProfileID) throws MoaSigServiceException;
- /**
- * Verify a XML or XAdES signature
- * <br><br>
- * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i>
- *
- * @param signature Serialized XML or XAdES signature
- * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
- * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found
- * @throws MOASigServiceException on signatue-verification error
- */
- IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID)
- throws MOASigServiceException;
+ /**
+ * Verify a XML or XAdES signature. <br>
+ * <br>
+ * <i>This method only validates the first XML or XAdES signature if more than
+ * one signature exists</i>
+ *
+ * @param signature Serialized XML or XAdES signature
+ * @param trustProfileID Id of the Trust-Profile from MOA-Sig
+ * configuration
+ * @param signatureLocationXpath Xpath that points to location of Signature
+ * element
+ * @return @link {@link IXmlSignatureVerificationResponse}, or null if no
+ * signature was found
+ * @throws MoaSigServiceException on signatue-verification error
+ */
+ IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID,
+ String signatureLocationXpath) throws MoaSigServiceException;
- /**
- * Verify a XML or XAdES signature
- * <br><br>
- * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i>
- *
- * @param signature Serialized XML or XAdES signature
- * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
- * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that should be used for signature-verification
- * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found
- * @throws MOASigServiceException on signatue-verification error
- */
- IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID,
- List<String> verifyTransformsInfoProfileID) throws MOASigServiceException;
+ /**
+ * Verify a XML or XAdES signature. <br>
+ * <br>
+ * <i>This method only validates the first XML or XAdES signature if more than
+ * one signature exists</i>
+ *
+ * @param signature Serialized XML or XAdES signature
+ * @param trustProfileID Id of the Trust-Profile from MOA-Sig
+ * configuration
+ * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that
+ * should be used for
+ * signature-verification
+ * @param signatureLocationXpath Xpath that points to location of
+ * Signature element
+ * @return @link {@link IXmlSignatureVerificationResponse}, or null if no
+ * signature was found
+ * @throws MoaSigServiceException on signatue-verification error
+ */
+ IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID,
+ List<String> verifyTransformsInfoProfileID, String signatureLocationXpath)
+ throws MoaSigServiceException;
-
- /**
- * Verify a XML or XAdES signature
- * <br><br>
- * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i>
- *
- * @param signature Serialized XML or XAdES signature
- * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
- * @param signatureLocationXpath Xpath that points to location of Signature element
- * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found
- * @throws MOASigServiceException on signatue-verification error
- */
- IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID,
- String signatureLocationXpath) throws MOASigServiceException;
-
- /**
- * Verify a XML or XAdES signature
- * <br><br>
- * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i>
- *
- * @param signature Serialized XML or XAdES signature
- * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration
- * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that should be used for signature-verification
- * @param signatureLocationXpath Xpath that points to location of Signature element
- * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found
- * @throws MOASigServiceException on signatue-verification error
- */
- IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID,
- List<String> verifyTransformsInfoProfileID,
- String signatureLocationXpath) throws MOASigServiceException;
-
-} \ No newline at end of file
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICMSSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICmsSignatureVerificationResponse.java
index 57426751..5e7a4564 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICMSSignatureVerificationResponse.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICmsSignatureVerificationResponse.java
@@ -1,5 +1,5 @@
package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data;
-public interface ICMSSignatureVerificationResponse extends IGenericSignatureVerificationResponse {
+public interface ICmsSignatureVerificationResponse extends IGenericSignatureVerificationResponse {
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java
index 00d98c86..8ebd90be 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java
@@ -1,69 +1,74 @@
package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data;
-import iaik.x509.X509Certificate;
import java.util.Date;
import org.springframework.lang.Nullable;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException;
-
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException;
+import iaik.x509.X509Certificate;
public interface IGenericSignatureVerificationResponse {
- /**
- * Returns the signing time
- *
- * @return Signing time, or null if signature contains no time information
- */
- @Nullable
- Date getSigningDateTime();
-
- /**
- * Returns the signatureCheckCode.
- * @return int
- */
- int getSignatureCheckCode();
-
- /**
- * Returns the certificateCheckCode.
- * @return int
- */
- int getCertificateCheckCode();
+ /**
+ * Returns the signing time.
+ *
+ * @return Signing time, or null if signature contains no time information
+ */
+ @Nullable
+ Date getSigningDateTime();
+
+ /**
+ * Returns the signatureCheckCode.
+ *
+ * @return int
+ */
+ int getSignatureCheckCode();
+
+ /**
+ * Returns the certificateCheckCode.
+ *
+ * @return int
+ */
+ int getCertificateCheckCode();
+
+ /**
+ * Returns the qualifiedCertificate.
+ *
+ * @return boolean
+ */
+ boolean isQualifiedCertificate();
+
+ /**
+ * Returns the X509 certificate.
+ *
+ * @return X509Certificate, or null if no certificate information exists
+ * @throws MoaSigServiceException if X509 certificate can not be deserialized
+ */
+ @Nullable
+ X509Certificate getX509Certificate() throws MoaSigServiceException;
- /**
- * Returns the qualifiedCertificate.
- * @return boolean
- */
- boolean isQualifiedCertificate();
+ /**
+ * Returns the X509 certificate in serialized form.
+ *
+ * @return Serialized X509 certificate, or null if no certificate information
+ * exists
+ */
+ @Nullable
+ byte[] getX509CertificateEncoded();
- /**
- * Returns the X509 certificate.
- * @return X509Certificate, or null if no certificate information exists
- * @throws MOASigServiceException if X509 certificate can not be deserialized
- */
- @Nullable
- X509Certificate getX509Certificate() throws MOASigServiceException;
+ /**
+ * Returns the publicAuthority.
+ *
+ * @return boolean
+ */
+ boolean isPublicAuthority();
-
- /**
- * Returns the X509 certificate in serialized form
- *
- * @return Serialized X509 certificate, or null if no certificate information exists
- */
- @Nullable
- byte[] getX509CertificateEncoded();
-
- /**
- * Returns the publicAuthority.
- * @return boolean
- */
- boolean isPublicAuthority();
-
- /**
- * Returns the publicAuthorityCode.
- * @return String OID, or null if no OID exists
- */
- @Nullable
- String getPublicAuthorityCode();
+ /**
+ * Returns the publicAuthorityCode.
+ *
+ * @return String OID, or null if no OID exists
+ */
+ @Nullable
+ String getPublicAuthorityCode();
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java
index 9548d96b..17d5fa59 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java
@@ -4,17 +4,18 @@ import java.io.InputStream;
import java.util.Map;
/**
- * Inject additional XML schemes into MOA-Sig
- *
+ * Inject additional XML schemes into MOA-Sig.
+ *
* @author tlenz
*
*/
public interface ISchemaRessourceProvider {
- /**
- * Get a Map of additional XML schemes that should be injected into MOA-Sig
- *
- * @return A Set of {@link Entry} consist of Name of the Scheme and XML scheme as {@link InputStream}
- */
- public Map<String, InputStream> getSchemas();
+ /**
+ * Get a Map of additional XML schemes that should be injected into MOA-Sig.
+ *
+ * @return A Set of {@link Entry} consist of Name of the Scheme and XML scheme
+ * as {@link InputStream}
+ */
+ Map<String, InputStream> getSchemas();
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java
deleted file mode 100644
index 3e86fb63..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data;
-
-/**
- * @author tlenz
- *
- */
-public interface IXMLSignatureVerificationResponse extends IGenericSignatureVerificationResponse {
-
-
- /**
- * Returns the xmlDSIGManifestCheckCode.
- * @return int
- */
- int getXmlDSIGManifestCheckCode();
-
- /**
- * Returns the xmlDsigSubjectName.
- * @return String
- */
- String getXmlDsigSubjectName();
-
-
- /**
- * Returns the xmlDSIGManigest.
- * @return boolean
- */
- boolean isXmlDSIGManigest();
-
-
- /**
- * Returns the the resulting code of the signature manifest check.
- *
- * @return The code of the sigature manifest check.
- */
- int getSignatureManifestCheckCode();
-
-} \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java
new file mode 100644
index 00000000..5b766917
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java
@@ -0,0 +1,39 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data;
+
+/**
+ * XML signature verification result.
+ *
+ * @author tlenz
+ *
+ */
+public interface IXmlSignatureVerificationResponse extends IGenericSignatureVerificationResponse {
+
+ /**
+ * Returns the xmlDSIGManifestCheckCode.
+ *
+ * @return int
+ */
+ int getXmlDsigManifestCheckCode();
+
+ /**
+ * Returns the xmlDsigSubjectName.
+ *
+ * @return String
+ */
+ String getXmlDsigSubjectName();
+
+ /**
+ * Returns the xmlDSIGManigest.
+ *
+ * @return boolean
+ */
+ boolean isXmlDsigManigest();
+
+ /**
+ * Returns the the resulting code of the signature manifest check.
+ *
+ * @return The code of the sigature manifest check.
+ */
+ int getSignatureManifestCheckCode();
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java
deleted file mode 100644
index ded3f900..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
-
-public class MOASigServiceBuilderException extends MOASigServiceException {
-
- private static final long serialVersionUID = 5178393157255309476L;
-
- public MOASigServiceBuilderException(String errorId, Object[] params) {
- super(errorId, params);
- }
-
- public MOASigServiceBuilderException(String errorId, Object[] params, Throwable e) {
- super(errorId, params, e);
- }
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java
deleted file mode 100644
index f3c02fe1..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
-
-public class MOASigServiceConfigurationException extends MOASigServiceException {
-
- private static final long serialVersionUID = -4710795384615456488L;
-
- public MOASigServiceConfigurationException(String errorId, Object[] params, Throwable e) {
- super(errorId, params, e);
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java
deleted file mode 100644
index 243b4b1d..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
-
-import at.gv.egiz.eaaf.core.exceptions.EAAFServiceException;
-
-public class MOASigServiceException extends EAAFServiceException {
-
- private static final long serialVersionUID = -6088238428550563658L;
- private static final String MOA_SIG_SERVICE_ID = "MOA-SIG-VERIFY";
-
- public MOASigServiceException(String errorId, Object[] params) {
- super(errorId, params);
-
- }
-
- public MOASigServiceException(String errorId, Object[] params, Throwable e) {
- super(errorId, params, e);
-
- }
-
- @Override
- protected String getServiceIdentifier() {
- return MOA_SIG_SERVICE_ID;
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java
deleted file mode 100644
index 63a51001..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
-
-public class MOASigServiceParserException extends MOASigServiceException {
-
- private static final long serialVersionUID = 5178393157255309476L;
-
- public MOASigServiceParserException(String errorId, Object[] params) {
- super(errorId, params);
- }
-
- public MOASigServiceParserException(String errorId, Object[] params, Throwable e) {
- super(errorId, params, e);
- }
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java
new file mode 100644
index 00000000..e32ab932
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java
@@ -0,0 +1,14 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
+
+public class MoaSigServiceBuilderException extends MoaSigServiceException {
+
+ private static final long serialVersionUID = 5178393157255309476L;
+
+ public MoaSigServiceBuilderException(final String errorId, final Object[] params) {
+ super(errorId, params);
+ }
+
+ public MoaSigServiceBuilderException(final String errorId, final Object[] params, final Throwable e) {
+ super(errorId, params, e);
+ }
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java
new file mode 100644
index 00000000..fd5f8caf
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java
@@ -0,0 +1,11 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
+
+public class MoaSigServiceConfigurationException extends MoaSigServiceException {
+
+ private static final long serialVersionUID = -4710795384615456488L;
+
+ public MoaSigServiceConfigurationException(final String errorId, final Object[] params, final Throwable e) {
+ super(errorId, params, e);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java
new file mode 100644
index 00000000..a4fb6290
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java
@@ -0,0 +1,26 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafServiceException;
+
+public class MoaSigServiceException extends EaafServiceException {
+
+ private static final long serialVersionUID = -6088238428550563658L;
+ private static final String MOA_SIG_SERVICE_ID = "MOA-SIG-VERIFY";
+
+ public MoaSigServiceException(final String errorId, final Object[] params) {
+ super(errorId, params);
+
+ }
+
+ public MoaSigServiceException(final String errorId, final Object[] params, final Throwable e) {
+ super(errorId, params, e);
+
+ }
+
+ @Override
+ protected String getServiceIdentifier() {
+ return MOA_SIG_SERVICE_ID;
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java
new file mode 100644
index 00000000..a47b45e0
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java
@@ -0,0 +1,14 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions;
+
+public class MoaSigServiceParserException extends MoaSigServiceException {
+
+ private static final long serialVersionUID = 5178393157255309476L;
+
+ public MoaSigServiceParserException(final String errorId, final Object[] params) {
+ super(errorId, params);
+ }
+
+ public MoaSigServiceParserException(final String errorId, final Object[] params, final Throwable e) {
+ super(errorId, params, e);
+ }
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java
index 7e65cec7..d2cab2ef 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java
@@ -3,75 +3,77 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.w3c.dom.Document;
+
import at.gv.egovernment.moa.spss.server.config.ConfigurationException;
import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider;
import at.gv.egovernment.moa.spss.server.iaik.config.IaikConfigurator;
-import at.gv.egovernment.moa.spss.server.logging.TransactionId;
import at.gv.egovernment.moa.spss.server.transaction.TransactionContext;
import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager;
import at.gv.egovernment.moaspss.logging.LoggingContext;
import at.gv.egovernment.moaspss.logging.LoggingContextManager;
-import iaik.server.Configurator;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.w3c.dom.Document;
public abstract class AbstractSignatureService {
- private static final Logger log = LoggerFactory.getLogger(AbstractSignatureService.class);
-
- @Autowired(required = true) MoaSigInitializer moaSigConfig;
-
- /**
- * Get a new {@link Document} from {@link DocumentBuilder} in synchronized form, because
- * {@link DocumentBuilderFactory} and {@link DocumentBuilder} are not thread-safe.
- *
- * @return {@link Document}
- * @throws ParserConfigurationException
- */
- protected synchronized Document getNewDocumentBuilder() throws ParserConfigurationException {
- final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- return docBuilder.newDocument();
-
- }
-
- /**
- * Set up the thread-local context information needed for calling the various
- * <code>Invoker</code> classes.
- *
- * @throws ConfigurationException An error occurred setting up the
- * configuration in the <code>TransactionContext</code>.
- */
- protected final void setUpContexts( String transactionID) throws ConfigurationException {
- final TransactionContextManager txMgr = TransactionContextManager.getInstance();
- final LoggingContextManager logMgr = LoggingContextManager.getInstance();
-
- if (txMgr.getTransactionContext() == null) {
- log.debug("Set not MOA-Sig transaction context");
- final TransactionContext ctx = new TransactionContext(transactionID, null, ConfigurationProvider.getInstance());
- txMgr.setTransactionContext(ctx);
-
- }
-
- if (logMgr.getLoggingContext() == null) {
- final LoggingContext ctx = new LoggingContext(transactionID);
- logMgr.setLoggingContext(ctx);
-
- }
-
- new IaikConfigurator().configure(ConfigurationProvider.getInstance());
-
- }
-
- /**
- * Tear down thread-local context information.
- */
- protected void tearDownContexts() {
- TransactionContextManager.getInstance().setTransactionContext(null);
- LoggingContextManager.getInstance().setLoggingContext(null);
- log.debug("Closing MOA-Sig transaction context");
-
- }
+ private static final Logger log = LoggerFactory.getLogger(AbstractSignatureService.class);
+
+ @Autowired(required = true)
+ MoaSigInitializer moaSigConfig;
+
+ /**
+ * Get a new {@link Document} from {@link DocumentBuilder} in synchronized form,
+ * because {@link DocumentBuilderFactory} and {@link DocumentBuilder} are not
+ * thread-safe.
+ *
+ * @return {@link Document}
+ * @throws ParserConfigurationException In case of an error
+ */
+ protected synchronized Document getNewDocumentBuilder() throws ParserConfigurationException {
+ final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ return docBuilder.newDocument();
+
+ }
+
+ /**
+ * Set up the thread-local context information needed for calling the various
+ * <code>Invoker</code> classes.
+ *
+ * @throws ConfigurationException An error occurred setting up the configuration
+ * in the <code>TransactionContext</code>.
+ */
+ protected final void setUpContexts(final String transactionID) throws ConfigurationException {
+ final TransactionContextManager txMgr = TransactionContextManager.getInstance();
+ final LoggingContextManager logMgr = LoggingContextManager.getInstance();
+
+ if (txMgr.getTransactionContext() == null) {
+ log.debug("Set not MOA-Sig transaction context");
+ final TransactionContext ctx =
+ new TransactionContext(transactionID, null, ConfigurationProvider.getInstance());
+ txMgr.setTransactionContext(ctx);
+
+ }
+
+ if (logMgr.getLoggingContext() == null) {
+ final LoggingContext ctx = new LoggingContext(transactionID);
+ logMgr.setLoggingContext(ctx);
+
+ }
+
+ new IaikConfigurator().configure(ConfigurationProvider.getInstance());
+
+ }
+
+ /**
+ * Tear down thread-local context information.
+ */
+ protected void tearDownContexts() {
+ TransactionContextManager.getInstance().setTransactionContext(null);
+ LoggingContextManager.getInstance().setLoggingContext(null);
+ log.debug("Closing MOA-Sig transaction context");
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java
deleted file mode 100644
index ecda7eb1..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl;
-
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-
-import at.gv.egiz.components.spring.api.SpringResourceProvider;
-
-public class MOASigSpringResourceProvider implements SpringResourceProvider {
-
- @Override
- public Resource[] getResourcesToLoad() {
- ClassPathResource moaSigConfig = new ClassPathResource("/moa-sig-service.beans.xml", MOASigSpringResourceProvider.class);
- return new Resource[] {moaSigConfig};
- }
-
- @Override
- public String[] getPackagesToScan() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String getName() {
- return "Signature-verification service based on MOA-Sig (MOA-SPSS)";
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java
index 1628b71a..77bbc88b 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java
@@ -9,118 +9,122 @@ import java.util.Map.Entry;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ISchemaRessourceProvider;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceConfigurationException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceConfigurationException;
import at.gv.egovernment.moa.spss.MOAException;
import at.gv.egovernment.moa.spss.api.Configurator;
import at.gv.egovernment.moaspss.logging.LoggingContext;
import at.gv.egovernment.moaspss.logging.LoggingContextManager;
import at.gv.egovernment.moaspss.util.DOMUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import iaik.asn1.structures.AlgorithmID;
import iaik.security.ec.provider.ECCelerate;
import iaik.security.provider.IAIK;
public class MoaSigInitializer {
- private static final Logger log = LoggerFactory.getLogger(MoaSigInitializer.class);
-
- @Autowired(required=false) ISchemaRessourceProvider[] schemas;
-
- private Configurator moaSigConfigurator;
-
-
- /**
- * Get MOA-Sig configuration object
- *
- * @return moa-sig configuration
- */
- @Nonnull
- public Configurator getMoaSigConfigurator() {
- return moaSigConfigurator;
-
- }
-
- @PostConstruct
- private synchronized void initialize() throws MOASigServiceConfigurationException {
- log.info("Initializing MOA-Sig signature-verification service ... ");
-
- log.info("Loading Java security providers.");
- IAIK.addAsProvider();
- ECCelerate.addAsProvider();
-
- try {
- LoggingContextManager.getInstance().setLoggingContext(
- new LoggingContext("startup"));
- log.debug("MOA-Sig library initialization process ... ");
- Configurator.getInstance().init();
- log.info("MOA-Sig library initialization complete ");
-
- Security.insertProviderAt(IAIK.getInstance(), 0);
-
- final ECCelerate eccProvider = ECCelerate.getInstance();
- if (Security.getProvider(eccProvider.getName()) != null)
- Security.removeProvider(eccProvider.getName());
- Security.addProvider(new ECCelerate());
-
- fixJava8_141ProblemWithSSLAlgorithms();
-
- if (log.isDebugEnabled()) {
- log.debug("Loaded Security Provider:");
- final Provider[] providerList = Security.getProviders();
- for (int i=0; i<providerList.length; i++)
- log.debug(i + ": " + providerList[i].getName() + " Version " + providerList[i].getVersion());
+ private static final Logger log = LoggerFactory.getLogger(MoaSigInitializer.class);
+
+ @Autowired(required = false)
+ ISchemaRessourceProvider[] schemas;
+
+ private Configurator moaSigConfigurator;
+
+ /**
+ * Get MOA-Sig configuration object.
+ *
+ * @return moa-sig configuration
+ */
+ @Nonnull
+ public Configurator getMoaSigConfigurator() {
+ return moaSigConfigurator;
+
+ }
+
+ @PostConstruct
+ private synchronized void initialize() throws MoaSigServiceConfigurationException {
+ log.info("Initializing MOA-Sig signature-verification service ... ");
+
+ log.info("Loading Java security providers.");
+ IAIK.addAsProvider();
+ ECCelerate.addAsProvider();
+
+ try {
+ LoggingContextManager.getInstance().setLoggingContext(new LoggingContext("startup"));
+ log.debug("MOA-Sig library initialization process ... ");
+ Configurator.getInstance().init();
+ log.info("MOA-Sig library initialization complete ");
+
+ Security.insertProviderAt(IAIK.getInstance(), 0);
+
+ final ECCelerate eccProvider = ECCelerate.getInstance();
+ if (Security.getProvider(eccProvider.getName()) != null) {
+ Security.removeProvider(eccProvider.getName());
+ }
+ Security.addProvider(new ECCelerate());
+
+ fixJava8_141ProblemWithSslAlgorithms();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Loaded Security Provider:");
+ final Provider[] providerList = Security.getProviders();
+ for (int i = 0; i < providerList.length; i++) {
+ log.debug(
+ i + ": " + providerList[i].getName() + " Version " + providerList[i].getVersion());
+ }
+
+ }
+
+ // Inject additional XML schemes
+ if (schemas != null && schemas.length > 0) {
+ log.debug("Infjecting additional XML schemes ... ");
+ for (final ISchemaRessourceProvider el : schemas) {
+ final Iterator<Entry<String, InputStream>> xmlSchemeIt =
+ el.getSchemas().entrySet().iterator();
+ while (xmlSchemeIt.hasNext()) {
+ final Entry<String, InputStream> xmlDef = xmlSchemeIt.next();
+ try {
+ DOMUtils.addSchemaToPool(xmlDef.getValue(), xmlDef.getKey());
+ log.info("Inject XML scheme: {}", xmlDef.getKey());
+
+ } catch (final IOException e) {
+ log.warn("Can NOT inject XML scheme: " + xmlDef.getKey(), e);
}
+ }
+ }
+ }
- //Inject additional XML schemes
- if (schemas != null && schemas.length > 0) {
- log.debug("Infjecting additional XML schemes ... ");
- for (final ISchemaRessourceProvider el : schemas) {
- final Iterator<Entry<String, InputStream>> xmlSchemeIt = el.getSchemas().entrySet().iterator();
- while (xmlSchemeIt.hasNext()) {
- final Entry<String, InputStream> xmlDef = xmlSchemeIt.next();
- try {
- DOMUtils.addSchemaToPool(xmlDef.getValue(), xmlDef.getKey());
- log.info("Inject XML scheme: {}", xmlDef.getKey());
-
- } catch (final IOException e) {
- log.warn("Can NOT inject XML scheme: " + xmlDef.getKey(), e);
+ moaSigConfigurator = Configurator.getInstance();
- }
-
- }
- }
- }
-
- moaSigConfigurator = Configurator.getInstance();
-
-
- } catch (final MOAException e) {
- log.error("MOA-SP initialization FAILED!", e.getWrapped());
- throw new MOASigServiceConfigurationException("service.moasig.04", new Object[] { e
- .toString() }, e);
- }
-
-
- }
-
- private static void fixJava8_141ProblemWithSSLAlgorithms() {
- log.info("Change AlgorithmIDs to fix problems with Java8 >= 141 ...");
- //new AlgorithmID("1.2.840.113549.1.1.4", "md5WithRSAEncryption", new String[] { "MD5withRSA", "MD5/RSA", }, null, true);
- new AlgorithmID("1.2.840.113549.1.1.5", "sha1WithRSAEncryption",
- new String[] { "SHA1withRSA" , "SHA1/RSA", "SHA-1/RSA", "SHA/RSA", }, null, true);
- new AlgorithmID("1.2.840.113549.1.1.14", "sha224WithRSAEncryption",
- new String[] { "SHA224withRSA", "SHA224/RSA", "SHA-224/RSA", }, null, true);
- new AlgorithmID("1.2.840.113549.1.1.11", "sha256WithRSAEncryption",
- new String[] { "SHA256withRSA", "SHA256/RSA", "SHA-256/RSA", }, null, true);
- new AlgorithmID("1.2.840.113549.1.1.12", "sha384WithRSAEncryption",
- new String[] { "SHA384withRSA", "SHA384/RSA", "SHA-384/RSA", }, null, true);
- new AlgorithmID("1.2.840.113549.1.1.13", "sha512WithRSAEncryption",
- new String[] { "SHA512withRSA", "SHA512/RSA", "SHA-512/RSA" }, null, true);
-
- log.info("Change AlgorithmIDs finished");
+ } catch (final MOAException e) {
+ log.error("MOA-SP initialization FAILED!", e.getWrapped());
+ throw new MoaSigServiceConfigurationException("service.moasig.04",
+ new Object[] { e.toString() }, e);
}
+
+ }
+
+ private static void fixJava8_141ProblemWithSslAlgorithms() {
+ log.info("Change AlgorithmIDs to fix problems with Java8 >= 141 ...");
+ // new AlgorithmID("1.2.840.113549.1.1.4", "md5WithRSAEncryption", new String[]
+ // { "MD5withRSA",
+ // "MD5/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.5", "sha1WithRSAEncryption",
+ new String[] { "SHA1withRSA", "SHA1/RSA", "SHA-1/RSA", "SHA/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.14", "sha224WithRSAEncryption",
+ new String[] { "SHA224withRSA", "SHA224/RSA", "SHA-224/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.11", "sha256WithRSAEncryption",
+ new String[] { "SHA256withRSA", "SHA256/RSA", "SHA-256/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.12", "sha384WithRSAEncryption",
+ new String[] { "SHA384withRSA", "SHA384/RSA", "SHA-384/RSA", }, null, true);
+ new AlgorithmID("1.2.840.113549.1.1.13", "sha512WithRSAEncryption",
+ new String[] { "SHA512withRSA", "SHA512/RSA", "SHA-512/RSA" }, null, true);
+
+ log.info("Change AlgorithmIDs finished");
+ }
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java
new file mode 100644
index 00000000..d09b26de
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java
@@ -0,0 +1,28 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+public class MoaSigSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource moaSigConfig =
+ new ClassPathResource("/moa-sig-service.beans.xml", MoaSigSpringResourceProvider.class);
+ return new Resource[] { moaSigConfig };
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return "Signature-verification service based on MOA-Sig (MOA-SPSS)";
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java
index 59e7b516..559af62a 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java
@@ -10,21 +10,23 @@ import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureCreatio
import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureCreationInvoker;
import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureCreationInvoker;
-@Service(value="moaSigCreateService")
-public class SignatureCreationService extends AbstractSignatureService implements ISignatureCreationService{
- private static final Logger log = LoggerFactory.getLogger(SignatureCreationService.class);
-
- private XMLSignatureCreationInvoker xadesInvoker;
- private CMSSignatureCreationInvoker cadesInvoker;
-
-
- @PostConstruct
- protected void internalInitializer() {
- log.debug("Instanzing SignatureCreationService implementation ... ");
- xadesInvoker = XMLSignatureCreationInvoker.getInstance();
- cadesInvoker = CMSSignatureCreationInvoker.getInstance();
- log.info("MOA-Sig signature-creation service initialized");
-
- }
+@Service(value = "moaSigCreateService")
+public class SignatureCreationService extends AbstractSignatureService
+ implements ISignatureCreationService {
+ private static final Logger log = LoggerFactory.getLogger(SignatureCreationService.class);
+
+ private XMLSignatureCreationInvoker xadesInvoker;
+ private CMSSignatureCreationInvoker cadesInvoker;
+
+ @PostConstruct
+ protected void internalInitializer() {
+ log.debug("Instanzing SignatureCreationService implementation ... ");
+ xadesInvoker = XMLSignatureCreationInvoker.getInstance();
+ cadesInvoker = CMSSignatureCreationInvoker.getInstance();
+ log.trace("XML_impl: {} , CMS_imp: {}",
+ xadesInvoker.getClass().getName(), cadesInvoker.getClass().getName());
+ log.info("MOA-Sig signature-creation service initialized");
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java
index f610e59e..8fc4086e 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java
@@ -3,13 +3,24 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateEncodingException;
import java.util.List;
+
import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Base64Utils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureVerificationService;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceBuilderException;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser.VerifyXMLSignatureResponseParser;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICmsSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceBuilderException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser.VerifyXmlSignatureResponseParser;
import at.gv.egovernment.moa.spss.MOAException;
import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest;
import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse;
@@ -22,281 +33,327 @@ import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker;
import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker;
import at.gv.egovernment.moaspss.util.Constants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.lang.Nullable;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Base64Utils;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
/**
+ * MOA-Sig based signature verification implementation.
+ *
* @author tlenz
*
*/
-@Service(value="moaSigVerifyService")
-public class SignatureVerificationService extends AbstractSignatureService implements ISignatureVerificationService {
- private static final Logger log = LoggerFactory.getLogger(SignatureVerificationService.class);
-
- private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI;
- private static final String MOA_NS_URI = Constants.MOA_NS_URI;
- private static final String DSIG = Constants.DSIG_PREFIX + ":";
- private static final String DEFAULT_XPATH_SIGNATURE_LOCATION = "//" + DSIG + "Signature";
-
- private CMSSignatureVerificationInvoker cadesInvoker;
- private XMLSignatureVerificationInvoker xadesInvocer;
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyCMSSignature(byte[], java.lang.String)
- */
- @Override
- @Nullable
- public ICMSSignatureVerificationResponse verifyCMSSignature(byte[] signature, String trustProfileID) throws MOASigServiceException {
- try {
- //setup context
- setUpContexts(Thread.currentThread().getName());
-
- //verify signature
- final VerifyCMSSignatureRequest cmsSigVerifyReq = buildVerfifyCMSRequest(signature, trustProfileID, false, false);
- final VerifyCMSSignatureResponse cmsSigVerifyResp = cadesInvoker.verifyCMSSignature(cmsSigVerifyReq );
- return parseCMSVerificationResult(cmsSigVerifyResp);
-
- } catch (final MOAException e) {
- log.warn("CMS signature verification has an error.", e);
- throw new MOASigServiceException("service.03", new Object[] { e.toString()}, e);
-
- } catch (final CertificateEncodingException e) {
- log.warn("Can NOT serialize X509 certificate from CMS/CAdES signature-verification response", e);
- throw new MOASigServiceException("service.03", new Object[] { e.toString()}, e);
-
- } finally {
- tearDownContexts();
+@Service(value = "moaSigVerifyService")
+public class SignatureVerificationService extends AbstractSignatureService
+ implements ISignatureVerificationService {
+ private static final Logger log = LoggerFactory.getLogger(SignatureVerificationService.class);
+
+ private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI;
+ private static final String MOA_NS_URI = Constants.MOA_NS_URI;
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+ private static final String DEFAULT_XPATH_SIGNATURE_LOCATION = "//" + DSIG + "Signature";
+
+ private CMSSignatureVerificationInvoker cadesInvoker;
+ private XMLSignatureVerificationInvoker xadesInvocer;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.
+ * ISignatureVerificationService# verifyCMSSignature(byte[], java.lang.String)
+ */
+ @Override
+ @Nullable
+ public ICmsSignatureVerificationResponse verifyCmsSignature(final byte[] signature,
+ final String trustProfileID) throws MoaSigServiceException {
+ try {
+ // setup context
+ setUpContexts(Thread.currentThread().getName());
+
+ // verify signature
+ final VerifyCMSSignatureRequest cmsSigVerifyReq =
+ buildVerfifyCmsRequest(signature, trustProfileID, false, false);
+ final VerifyCMSSignatureResponse cmsSigVerifyResp =
+ cadesInvoker.verifyCMSSignature(cmsSigVerifyReq);
+ return parseCmsVerificationResult(cmsSigVerifyResp);
+
+ } catch (final MOAException e) {
+ log.warn("CMS signature verification has an error.", e);
+ throw new MoaSigServiceException("service.03", new Object[] { e.toString() }, e);
+
+ } catch (final CertificateEncodingException e) {
+ log.warn("Can NOT serialize X509 certificate from CMS/CAdES signature-verification response",
+ e);
+ throw new MoaSigServiceException("service.03", new Object[] { e.toString() }, e);
+
+ } finally {
+ tearDownContexts();
+
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.
+ * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String)
+ */
+ @Override
+ public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature,
+ final String trustProfileID) throws MoaSigServiceException {
+ return verifyXmlSignature(signature, trustProfileID, null, DEFAULT_XPATH_SIGNATURE_LOCATION);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.
+ * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String,
+ * java.util.List)
+ */
+ @Override
+ public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature,
+ final String trustProfileID, final List<String> verifyTransformsInfoProfileID)
+ throws MoaSigServiceException {
+ return verifyXmlSignature(signature, trustProfileID, verifyTransformsInfoProfileID,
+ DEFAULT_XPATH_SIGNATURE_LOCATION);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.
+ * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String,
+ * java.lang.String)
+ */
+ @Override
+ public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature,
+ final String trustProfileID, final String signatureLocationXpath)
+ throws MoaSigServiceException {
+ return verifyXmlSignature(signature, trustProfileID, null, signatureLocationXpath);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.
+ * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String,
+ * java.util.List, java.lang.String)
+ */
+ @Override
+ public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature,
+ final String trustProfileID, final List<String> verifyTransformsInfoProfileID,
+ final String xpathSignatureLocation) throws MoaSigServiceException {
+ try {
+ // setup context
+ setUpContexts(Thread.currentThread().getName());
+
+ // build signature-verification request
+ final Element domVerifyXmlSignatureRequest = buildVerifyXmlRequest(signature, trustProfileID,
+ verifyTransformsInfoProfileID, xpathSignatureLocation);
+
+ // send signature-verification to MOA-Sig
+ final VerifyXMLSignatureRequest vsrequest =
+ new VerifyXMLSignatureRequestParser().parse(domVerifyXmlSignatureRequest);
+ final VerifyXMLSignatureResponse vsresponse = xadesInvocer.verifyXMLSignature(vsrequest);
+ final Document result = new VerifyXMLSignatureResponseBuilder(true).build(vsresponse);
+
+ // parses the <IXMLSignatureVerificationResponse>
+ final IXmlSignatureVerificationResponse verifyXmlSignatureResponse =
+ new VerifyXmlSignatureResponseParser(result.getDocumentElement()).parseData();
+
+ return verifyXmlSignatureResponse;
+
+ } catch (final MoaSigServiceException e) {
+ throw e;
+
+ } catch (final MOAException e) {
+ log.warn("MOA-Sig signature-verification has an internal error." + " MsgCode: "
+ + e.getMessageId() + " Msg: " + e.getMessage(), e);
+ throw new MoaSigServiceException("service.moasig.03", new Object[] { e.getMessage() }, e);
+
+ } finally {
+ tearDownContexts();
+
+ }
+ }
+
+ private ICmsSignatureVerificationResponse parseCmsVerificationResult(
+ final VerifyCMSSignatureResponse cmsSigVerifyResp) throws CertificateEncodingException {
+
+ if (cmsSigVerifyResp.getResponseElements() == null
+ || cmsSigVerifyResp.getResponseElements().isEmpty()) {
+ log.info("No CMS signature FOUND. ");
+ return null;
+
+ }
+
+ if (cmsSigVerifyResp.getResponseElements().size() > 1) {
+ log.warn(
+ "CMS or CAdES signature contains more than one technical signatures. Only validate the first signature");
+ }
+
+ final VerifyCMSSignatureResponseElement firstSig =
+ (VerifyCMSSignatureResponseElement) cmsSigVerifyResp.getResponseElements().get(0);
+
+ final at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCmsSignatureResponse result =
+ new at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCmsSignatureResponse();
+
+ // parse results into response container
+ result.setSignatureCheckCode(firstSig.getSignatureCheck().getCode());
+ result.setCertificateCheckCode(firstSig.getCertificateCheck().getCode());
+
+ if (firstSig.getSignerInfo() != null) {
+ result.setSigningDateTime(firstSig.getSignerInfo().getSigningTime());
+ result
+ .setX509CertificateEncoded(firstSig.getSignerInfo().getSignerCertificate().getEncoded());
+ result.setQualifiedCertificate(firstSig.getSignerInfo().isQualifiedCertificate());
+
+ result.setPublicAuthority(firstSig.getSignerInfo().isPublicAuthority());
+ result.setPublicAuthorityCode(firstSig.getSignerInfo().getPublicAuhtorityID());
+
+ } else {
+ log.info("CMS or CAdES verification result contains no SignerInfo");
+ }
+
+ return result;
+ }
+
+ /**
+ * Build a VerifyCMS-Siganture request for MOA-Sig. <br>
+ * <br>
+ * This builder only generates verification-request for enveloped CMS or CAdES
+ * signatures <br>
+ * This
+ *
+ * @param signature CMS or CAdES signature
+ * @param trustProfileID trustProfileID MOA-Sig Trust-Profile
+ * @param isPdfSignature Make CAdES signature as part of an PAdES
+ * document
+ * @param performExtendedValidation To extended validation. See MOA-Sig
+ * documentation for detailed information
+ * @return
+ */
+ private VerifyCMSSignatureRequest buildVerfifyCmsRequest(final byte[] signature,
+ final String trustProfileID, final boolean isPdfSignature,
+ final boolean performExtendedValidation) {
+ final VerifyCMSSignatureRequestImpl verifyCmsSignatureRequest =
+ new VerifyCMSSignatureRequestImpl();
+ verifyCmsSignatureRequest.setDateTime(null);
+ verifyCmsSignatureRequest.setCMSSignature(new ByteArrayInputStream(signature));
+ verifyCmsSignatureRequest.setDataObject(null);
+ verifyCmsSignatureRequest.setTrustProfileId(trustProfileID);
+ verifyCmsSignatureRequest.setSignatories(VerifyCMSSignatureRequest.ALL_SIGNATORIES);
+ verifyCmsSignatureRequest.setPDF(isPdfSignature);
+ verifyCmsSignatureRequest.setExtended(performExtendedValidation);
+ return verifyCmsSignatureRequest;
+
+ }
+
+ /**
+ * Build a VerifyXML-Signature request for MOA-Sig.
+ *
+ * @param signature Serialized XML signature
+ * @param trustProfileID MOA-Sig Trust-Profile
+ * @param verifyTransformsInfoProfileID {@link List} of Transformation-Profiles
+ * used for validation
+ * @param xpathSignatureLocation Xpath that points to location of
+ * Signature element
+ * @return MOA-Sig verification request element
+ * @throws MoaSigServiceBuilderException In case of an error
+ */
+ private Element buildVerifyXmlRequest(final byte[] signature, final String trustProfileID,
+ final List<String> verifyTransformsInfoProfileID, final String xpathSignatureLocation)
+ throws MoaSigServiceBuilderException {
+ try {
+ // build empty document
+ final Document requestDoc_ = getNewDocumentBuilder();
+ final Element requestElem_ =
+ requestDoc_.createElementNS(MOA_NS_URI, "VerifyXMLSignatureRequest");
+ requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI);
+ requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns:" + Constants.DSIG_PREFIX,
+ Constants.DSIG_NS_URI);
+ requestDoc_.appendChild(requestElem_);
+
+ // build the request
+ final Element verifiySignatureInfoElem =
+ requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureInfo");
+ requestElem_.appendChild(verifiySignatureInfoElem);
+ final Element verifySignatureEnvironmentElem =
+ requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureEnvironment");
+ verifiySignatureInfoElem.appendChild(verifySignatureEnvironmentElem);
+ final Element base64ContentElem = requestDoc_.createElementNS(MOA_NS_URI, "Base64Content");
+ verifySignatureEnvironmentElem.appendChild(base64ContentElem);
+
+ // insert the base64 encoded signature
+ String base64EncodedAssertion = Base64Utils.encodeToString(signature);
+ // replace all '\r' characters by no char.
+ final StringBuffer replaced = new StringBuffer();
+ for (int i = 0; i < base64EncodedAssertion.length(); i++) {
+ final char c = base64EncodedAssertion.charAt(i);
+ if (c != '\r') {
+ replaced.append(c);
+ }
+ }
+ base64EncodedAssertion = replaced.toString();
+ final Node base64Content = requestDoc_.createTextNode(base64EncodedAssertion);
+ base64ContentElem.appendChild(base64Content);
+
+ // specify the signature location
+ final Element verifySignatureLocationElem =
+ requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureLocation");
+ verifiySignatureInfoElem.appendChild(verifySignatureLocationElem);
+ final Node signatureLocation = requestDoc_.createTextNode(xpathSignatureLocation);
+ verifySignatureLocationElem.appendChild(signatureLocation);
+
+ // signature manifest params
+ if (verifyTransformsInfoProfileID != null && !verifyTransformsInfoProfileID.isEmpty()) {
+ final Element signatureManifestCheckParamsElem =
+ requestDoc_.createElementNS(MOA_NS_URI, "SignatureManifestCheckParams");
+ requestElem_.appendChild(signatureManifestCheckParamsElem);
+ signatureManifestCheckParamsElem.setAttribute("ReturnReferenceInputData", "false");
+
+ // verify transformations
+ final Element referenceInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "ReferenceInfo");
+ signatureManifestCheckParamsElem.appendChild(referenceInfoElem);
+ for (final String element : verifyTransformsInfoProfileID) {
+ final Element verifyTransformsInfoProfileIdElem =
+ requestDoc_.createElementNS(MOA_NS_URI, "VerifyTransformsInfoProfileID");
+ referenceInfoElem.appendChild(verifyTransformsInfoProfileIdElem);
+ verifyTransformsInfoProfileIdElem.appendChild(requestDoc_.createTextNode(element));
}
+ }
- }
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String)
- */
- @Override
- public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID) throws MOASigServiceException {
- return verifyXMLSignature(signature, trustProfileID, null, DEFAULT_XPATH_SIGNATURE_LOCATION);
-
- }
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.util.List)
- */
- @Override
- public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID) throws MOASigServiceException {
- return verifyXMLSignature(signature, trustProfileID, verifyTransformsInfoProfileID, DEFAULT_XPATH_SIGNATURE_LOCATION);
- }
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.lang.String)
- */
- @Override
- public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, String signatureLocationXpath) throws MOASigServiceException {
- return verifyXMLSignature(signature, trustProfileID, null, signatureLocationXpath);
- }
-
- /* (non-Javadoc)
- * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.util.List, java.lang.String)
- */
- @Override
- public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID, String xpathSignatureLocation) throws MOASigServiceException {
- try {
- //setup context
- setUpContexts(Thread.currentThread().getName());
-
- //build signature-verification request
- final Element domVerifyXMLSignatureRequest = buildVerifyXMLRequest(signature, trustProfileID, verifyTransformsInfoProfileID, xpathSignatureLocation);
-
- //send signature-verification to MOA-Sig
- final VerifyXMLSignatureRequest vsrequest = new VerifyXMLSignatureRequestParser().parse(domVerifyXMLSignatureRequest);
- final VerifyXMLSignatureResponse vsresponse = xadesInvocer.verifyXMLSignature(vsrequest);
- final Document result = new VerifyXMLSignatureResponseBuilder(true).build(vsresponse);
-
- // parses the <IXMLSignatureVerificationResponse>
- final IXMLSignatureVerificationResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(result.getDocumentElement()).parseData();
-
- return verifyXMLSignatureResponse;
-
- } catch (final MOASigServiceException e) {
- throw e;
-
- } catch (final MOAException e) {
- log.warn("MOA-Sig signature-verification has an internal error."
- + " MsgCode: " + e.getMessageId()
- + " Msg: " + e.getMessage(),
- e);
- throw new MOASigServiceException("service.moasig.03", new Object[]{e.getMessage()}, e);
-
- } finally {
- tearDownContexts();
+ // hashinput data
+ final Element returnHashInputDataElem =
+ requestDoc_.createElementNS(MOA_NS_URI, "ReturnHashInputData");
+ requestElem_.appendChild(returnHashInputDataElem);
- }
- }
-
-private ICMSSignatureVerificationResponse parseCMSVerificationResult(VerifyCMSSignatureResponse cmsSigVerifyResp) throws CertificateEncodingException {
-
- if (cmsSigVerifyResp.getResponseElements() == null ||
- cmsSigVerifyResp.getResponseElements().isEmpty()) {
- log.info("No CMS signature FOUND. ");
- return null;
-
- }
-
- if (cmsSigVerifyResp.getResponseElements().size() > 1)
- log.warn("CMS or CAdES signature contains more than one technical signatures. Only validate the first signature");
-
- final VerifyCMSSignatureResponseElement firstSig = (VerifyCMSSignatureResponseElement) cmsSigVerifyResp.getResponseElements().get(0);
-
- final at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCMSSignatureResponse result =
- new at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCMSSignatureResponse();
-
- //parse results into response container
- result.setSignatureCheckCode(firstSig.getSignatureCheck().getCode());
- result.setCertificateCheckCode(firstSig.getCertificateCheck().getCode());
-
- if (firstSig.getSignerInfo() != null) {
- result.setSigningDateTime(firstSig.getSignerInfo().getSigningTime());
- result.setX509CertificateEncoded(firstSig.getSignerInfo().getSignerCertificate().getEncoded());
- result.setQualifiedCertificate(firstSig.getSignerInfo().isQualifiedCertificate());
-
- result.setPublicAuthority(firstSig.getSignerInfo().isPublicAuthority());
- result.setPublicAuthorityCode(firstSig.getSignerInfo().getPublicAuhtorityID());
-
- } else
- log.info("CMS or CAdES verification result contains no SignerInfo");
-
- return result;
- }
-
- /**
- * Build a VerifyCMS-Siganture request for MOA-Sig.
- * <br><br>
- * This builder only generates verification-request for enveloped CMS or CAdES signatures
- * <br>
- * This
- *
- * @param signature CMS or CAdES signature
- * @param trustProfileID trustProfileID MOA-Sig Trust-Profile
- * @param isPdfSignature Make CAdES signature as part of an PAdES document
- * @param performExtendedValidation To extended validation. See MOA-Sig documentation for detailed information
- * @return
- */
- private VerifyCMSSignatureRequest buildVerfifyCMSRequest(byte[] signature, String trustProfileID,
- boolean isPdfSignature, boolean performExtendedValidation) {
- final VerifyCMSSignatureRequestImpl verifyCMSSignatureRequest = new VerifyCMSSignatureRequestImpl();
- verifyCMSSignatureRequest.setDateTime(null);
- verifyCMSSignatureRequest.setCMSSignature(new ByteArrayInputStream(signature));
- verifyCMSSignatureRequest.setDataObject(null);
- verifyCMSSignatureRequest.setTrustProfileId(trustProfileID);
- verifyCMSSignatureRequest.setSignatories(VerifyCMSSignatureRequest.ALL_SIGNATORIES);
- verifyCMSSignatureRequest.setPDF(isPdfSignature);
- verifyCMSSignatureRequest.setExtended(performExtendedValidation);
- return verifyCMSSignatureRequest;
-
- }
-
- /**
- * Build a VerifyXML-Signature request for MOA-Sig
- *
- * @param signature Serialized XML signature
- * @param trustProfileID MOA-Sig Trust-Profile
- * @param verifyTransformsInfoProfileID {@link List} of Transformation-Profiles used for validation
- * @param xpathSignatureLocation Xpath that points to location of Signature element
- * @return
- * @throws MOASigServiceBuilderException
- */
- private Element buildVerifyXMLRequest(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID, String xpathSignatureLocation) throws MOASigServiceBuilderException {
- try {
- //build empty document
- final Document requestDoc_ = getNewDocumentBuilder();
- final Element requestElem_ = requestDoc_.createElementNS(MOA_NS_URI, "VerifyXMLSignatureRequest");
- requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI);
- requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns:" + Constants.DSIG_PREFIX, Constants.DSIG_NS_URI);
- requestDoc_.appendChild(requestElem_);
-
-
- // build the request
- final Element verifiySignatureInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureInfo");
- requestElem_.appendChild(verifiySignatureInfoElem);
- final Element verifySignatureEnvironmentElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureEnvironment");
- verifiySignatureInfoElem.appendChild(verifySignatureEnvironmentElem);
- final Element base64ContentElem = requestDoc_.createElementNS(MOA_NS_URI, "Base64Content");
- verifySignatureEnvironmentElem.appendChild(base64ContentElem);
-
- // insert the base64 encoded signature
- String base64EncodedAssertion = Base64Utils.encodeToString(signature);
- //replace all '\r' characters by no char.
- final StringBuffer replaced = new StringBuffer();
- for (int i = 0; i < base64EncodedAssertion.length(); i ++) {
- final char c = base64EncodedAssertion.charAt(i);
- if (c != '\r') {
- replaced.append(c);
- }
- }
- base64EncodedAssertion = replaced.toString();
- final Node base64Content = requestDoc_.createTextNode(base64EncodedAssertion);
- base64ContentElem.appendChild(base64Content);
-
- // specify the signature location
- final Element verifySignatureLocationElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureLocation");
- verifiySignatureInfoElem.appendChild(verifySignatureLocationElem);
- final Node signatureLocation = requestDoc_.createTextNode(xpathSignatureLocation);
- verifySignatureLocationElem.appendChild(signatureLocation);
-
- // signature manifest params
- if (verifyTransformsInfoProfileID != null && !verifyTransformsInfoProfileID.isEmpty()) {
- final Element signatureManifestCheckParamsElem = requestDoc_.createElementNS(MOA_NS_URI, "SignatureManifestCheckParams");
- requestElem_.appendChild(signatureManifestCheckParamsElem);
- signatureManifestCheckParamsElem.setAttribute("ReturnReferenceInputData", "false");
-
- //verify transformations
- final Element referenceInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "ReferenceInfo");
- signatureManifestCheckParamsElem.appendChild(referenceInfoElem);
- for (final String element : verifyTransformsInfoProfileID) {
- final Element verifyTransformsInfoProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifyTransformsInfoProfileID");
- referenceInfoElem.appendChild(verifyTransformsInfoProfileIDElem);
- verifyTransformsInfoProfileIDElem.appendChild(requestDoc_.createTextNode(element));
-
- }
- }
-
- //hashinput data
- final Element returnHashInputDataElem = requestDoc_.createElementNS(MOA_NS_URI, "ReturnHashInputData");
- requestElem_.appendChild(returnHashInputDataElem);
-
- //add trustProfileID
- final Element trustProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "TrustProfileID");
- trustProfileIDElem.appendChild(requestDoc_.createTextNode(trustProfileID));
- requestElem_.appendChild(trustProfileIDElem);
-
- return requestElem_;
-
- } catch (final Throwable t) {
- log.warn("Can NOT build VerifyXML-Signature request for MOA-Sig", t);
- throw new MOASigServiceBuilderException("service.moasig.03", new Object[] { t.getMessage() }, t);
-
- }
-
- }
-
-
-
- @PostConstruct
- protected void internalInitializer() {
- log.debug("Instanzing SignatureVerificationService implementation ... ");
- //svs = at.gv.egovernment.moa.spss.api.SignatureVerificationService.getInstance();
- cadesInvoker = CMSSignatureVerificationInvoker.getInstance();
- xadesInvocer = XMLSignatureVerificationInvoker.getInstance();
- log.info("MOA-Sig signature-verification service initialized");
-
- }
+ // add trustProfileID
+ final Element trustProfileIdElem = requestDoc_.createElementNS(MOA_NS_URI, "TrustProfileID");
+ trustProfileIdElem.appendChild(requestDoc_.createTextNode(trustProfileID));
+ requestElem_.appendChild(trustProfileIdElem);
+
+ return requestElem_;
+
+ } catch (final Throwable t) {
+ log.warn("Can NOT build VerifyXML-Signature request for MOA-Sig", t);
+ throw new MoaSigServiceBuilderException("service.moasig.03", new Object[] { t.getMessage() },
+ t);
+
+ }
+
+ }
+
+ @PostConstruct
+ protected void internalInitializer() {
+ log.debug("Instanzing SignatureVerificationService implementation ... ");
+ // svs =
+ // at.gv.egovernment.moa.spss.api.SignatureVerificationService.getInstance();
+ cadesInvoker = CMSSignatureVerificationInvoker.getInstance();
+ xadesInvocer = XMLSignatureVerificationInvoker.getInstance();
+ log.info("MOA-Sig signature-verification service initialized");
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java
index f3c724d8..0485f31f 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java
@@ -2,129 +2,151 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data;
import java.io.Serializable;
import java.security.cert.CertificateException;
-import iaik.x509.X509Certificate;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IGenericSignatureVerificationResponse;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceParserException;
-
-public class GenericSignatureVerificationResponse implements IGenericSignatureVerificationResponse, Serializable {
-
- private static final long serialVersionUID = -7751001050689401118L;
- private static final Logger log = LoggerFactory.getLogger(GenericSignatureVerificationResponse.class);
-
-
- /** The signing time */
- private Date signingDateTime;
-
- /** The signatureCheckCode to be stored */
- private int signatureCheckCode;
-
- /** The certificateCheckCode to be stored */
- private int certificateCheckCode;
-
- /** The publicAuthority to be stored */
- private boolean publicAuthority;
-
- /** The publicAuthorityCode to be stored */
- private String publicAuthorityCode;
-
- /** The qualifiedCertificate to be stored */
- private boolean qualifiedCertificate;
-
- private byte[] x509CertificateEncoded;
-
- @Override
- public Date getSigningDateTime() {
- return this.signingDateTime;
-
- }
-
- @Override
- public int getSignatureCheckCode() {
- return this.signatureCheckCode;
-
- }
-
- @Override
- public int getCertificateCheckCode() {
- return this.certificateCheckCode;
-
- }
-
- @Override
- public boolean isQualifiedCertificate() {
- return this.qualifiedCertificate;
-
- }
-
- @Override
- public X509Certificate getX509Certificate() throws MOASigServiceException {
- if (x509CertificateEncoded != null) {
- try {
- return new X509Certificate(x509CertificateEncoded);
-
- } catch (CertificateException e) {
- log.error("Can NOT parse X509 certifcate in " + GenericSignatureVerificationResponse.class.getName(), e);
- throw new MOASigServiceParserException("service.moasig.01", null, e);
- }
-
- }
-
- return null;
-
- }
-
- @Override
- public byte[] getX509CertificateEncoded() {
- return this.getX509CertificateEncoded();
-
- }
-
- @Override
- public boolean isPublicAuthority() {
- return this.publicAuthority;
-
- }
-
- @Override
- public String getPublicAuthorityCode() {
- return this.publicAuthorityCode;
-
- }
-
- public void setSigningDateTime(Date signingDateTime) {
- this.signingDateTime = signingDateTime;
- }
-
- public void setSignatureCheckCode(int signatureCheckCode) {
- this.signatureCheckCode = signatureCheckCode;
- }
-
- public void setCertificateCheckCode(int certificateCheckCode) {
- this.certificateCheckCode = certificateCheckCode;
- }
-
- public void setPublicAuthority(boolean publicAuthority) {
- this.publicAuthority = publicAuthority;
- }
-
- public void setPublicAuthorityCode(String publicAuthorityCode) {
- this.publicAuthorityCode = publicAuthorityCode;
- }
-
- public void setQualifiedCertificate(boolean qualifiedCertificate) {
- this.qualifiedCertificate = qualifiedCertificate;
- }
-
- public void setX509CertificateEncoded(byte[] x509CertificateEncoded) {
- this.x509CertificateEncoded = x509CertificateEncoded;
- }
-
-
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceParserException;
+import iaik.x509.X509Certificate;
+
+public class GenericSignatureVerificationResponse
+ implements IGenericSignatureVerificationResponse, Serializable {
+
+ private static final long serialVersionUID = -7751001050689401118L;
+ private static final Logger log =
+ LoggerFactory.getLogger(GenericSignatureVerificationResponse.class);
+
+ /** The signing time. */
+ private Date signingDateTime;
+
+ /** The signatureCheckCode to be stored. */
+ private int signatureCheckCode;
+
+ /** The certificateCheckCode to be stored. */
+ private int certificateCheckCode;
+
+ /** The publicAuthority to be stored. */
+ private boolean publicAuthority;
+
+ /** The publicAuthorityCode to be stored. */
+ private String publicAuthorityCode;
+
+ /** The qualifiedCertificate to be stored. */
+ private boolean qualifiedCertificate;
+
+ private byte[] x509CertificateEncoded;
+
+ @Override
+ public Date getSigningDateTime() {
+ if (this.signingDateTime != null) {
+ return new Date(this.signingDateTime.getTime());
+ }
+ return null;
+
+ }
+
+ @Override
+ public int getSignatureCheckCode() {
+ return this.signatureCheckCode;
+
+ }
+
+ @Override
+ public int getCertificateCheckCode() {
+ return this.certificateCheckCode;
+
+ }
+
+ @Override
+ public boolean isQualifiedCertificate() {
+ return this.qualifiedCertificate;
+
+ }
+
+ @Override
+ public X509Certificate getX509Certificate() throws MoaSigServiceException {
+ if (x509CertificateEncoded != null) {
+ try {
+ return new X509Certificate(x509CertificateEncoded);
+
+ } catch (final CertificateException e) {
+ log.error("Can NOT parse X509 certifcate in "
+ + GenericSignatureVerificationResponse.class.getName(), e);
+ throw new MoaSigServiceParserException("service.moasig.01", null, e);
+ }
+
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public byte[] getX509CertificateEncoded() {
+ if (this.x509CertificateEncoded != null) {
+ return this.x509CertificateEncoded.clone();
+
+ }
+ return null;
+
+ }
+
+ @Override
+ public boolean isPublicAuthority() {
+ return this.publicAuthority;
+
+ }
+
+ @Override
+ public String getPublicAuthorityCode() {
+ return this.publicAuthorityCode;
+
+ }
+
+ /**
+ * Set signature creation timestramp.
+ *
+ * @param signingDateTime timestamp
+ */
+ public void setSigningDateTime(final Date signingDateTime) {
+ if (signingDateTime != null) {
+ this.signingDateTime = new Date(signingDateTime.getTime());
+ }
+ }
+
+ public void setSignatureCheckCode(final int signatureCheckCode) {
+ this.signatureCheckCode = signatureCheckCode;
+ }
+
+ public void setCertificateCheckCode(final int certificateCheckCode) {
+ this.certificateCheckCode = certificateCheckCode;
+ }
+
+ public void setPublicAuthority(final boolean publicAuthority) {
+ this.publicAuthority = publicAuthority;
+ }
+
+ public void setPublicAuthorityCode(final String publicAuthorityCode) {
+ this.publicAuthorityCode = publicAuthorityCode;
+ }
+
+ public void setQualifiedCertificate(final boolean qualifiedCertificate) {
+ this.qualifiedCertificate = qualifiedCertificate;
+ }
+
+ /**
+ * Set encoded signer certificate.
+ *
+ * @param x509CertificateEncoded signer cerificate
+ */
+ public void setX509CertificateEncoded(final byte[] x509CertificateEncoded) {
+ if (x509CertificateEncoded != null) {
+ this.x509CertificateEncoded = x509CertificateEncoded.clone();
+
+ }
+ }
}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java
deleted file mode 100644
index 2c177c71..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data;
-
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse;
-
-public class VerifyCMSSignatureResponse extends GenericSignatureVerificationResponse implements ICMSSignatureVerificationResponse{
-
- private static final long serialVersionUID = 708260904158070696L;
-
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java
new file mode 100644
index 00000000..ed679828
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java
@@ -0,0 +1,10 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data;
+
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICmsSignatureVerificationResponse;
+
+public class VerifyCmsSignatureResponse extends GenericSignatureVerificationResponse
+ implements ICmsSignatureVerificationResponse {
+
+ private static final long serialVersionUID = 708260904158070696L;
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java
deleted file mode 100644
index 0646bda7..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data;
-
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse;
-
-/**
- *
- *
- * @author tlenz
- *
- */
-
-public class VerifyXMLSignatureResponse extends GenericSignatureVerificationResponse implements IXMLSignatureVerificationResponse {
-
- private static final long serialVersionUID = 8386070769565711601L;
-
-/** The xmlDsigSubjectName to be stored */
- private String xmlDsigSubjectName;
-
- /** The xmlDSIGManifestCheckCode to be stored */
- private int xmlDSIGManifestCheckCode;
- /** The xmlDSIGManigest to be stored */
- private boolean xmlDSIGManigest;
-
- /**
- * The result of the signature manifest check. The default value <code>-1</code>
- * indicates that the signature manifest has not been checked.
- */
- private int signatureManifestCheckCode = -1;
-
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#getXmlDSIGManifestCheckCode()
- */
- @Override
-public int getXmlDSIGManifestCheckCode() {
- return xmlDSIGManifestCheckCode;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#getXmlDsigSubjectName()
- */
- @Override
-public String getXmlDsigSubjectName() {
- return xmlDsigSubjectName;
- }
-
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setXmlDSIGManifestCheckCode(int)
- */
-public void setXmlDSIGManifestCheckCode(int xmlDSIGManifestCheckCode) {
- this.xmlDSIGManifestCheckCode = xmlDSIGManifestCheckCode;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setXmlDsigSubjectName(java.lang.String)
- */
-public void setXmlDsigSubjectName(String xmlDsigSubjectName) {
- this.xmlDsigSubjectName = xmlDsigSubjectName;
- }
-
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#isXmlDSIGManigest()
- */
- @Override
-public boolean isXmlDSIGManigest() {
- return xmlDSIGManigest;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setXmlDSIGManigest(boolean)
- */
-public void setXmlDSIGManigest(boolean xmlDSIGManigest) {
- this.xmlDSIGManigest = xmlDSIGManigest;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#getSignatureManifestCheckCode()
- */
- @Override
-public int getSignatureManifestCheckCode() {
- return signatureManifestCheckCode;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setSignatureManifestCheckCode(int)
- */
-public void setSignatureManifestCheckCode(int signatureManifestCheckCode) {
- this.signatureManifestCheckCode = signatureManifestCheckCode;
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java
new file mode 100644
index 00000000..4b0632b1
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java
@@ -0,0 +1,115 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data;
+
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse;
+
+/**
+ * MOA-Sig signature verification response for XML based signatures.
+ *
+ * @author tlenz
+ *
+ */
+
+public class VerifyXmlSignatureResponse extends GenericSignatureVerificationResponse
+ implements IXmlSignatureVerificationResponse {
+
+ private static final long serialVersionUID = 8386070769565711601L;
+
+ /** The xmlDsigSubjectName to be stored. */
+ private String xmlDsigSubjectName;
+
+ /** The xmlDSIGManifestCheckCode to be stored. */
+ private int xmlDsigManifestCheckCode;
+ /** The xmlDSIGManigest to be stored. */
+ private boolean xmlDsigManigest;
+
+ /**
+ * The result of the signature manifest check. The default value <code>-1</code>
+ * indicates that the signature manifest has not been checked.
+ */
+ private int signatureManifestCheckCode = -1;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * getXmlDSIGManifestCheckCode()
+ */
+ @Override
+ public int getXmlDsigManifestCheckCode() {
+ return xmlDsigManifestCheckCode;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * getXmlDsigSubjectName()
+ */
+ @Override
+ public String getXmlDsigSubjectName() {
+ return xmlDsigSubjectName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * setXmlDSIGManifestCheckCode( int)
+ */
+ public void setXmlDsigManifestCheckCode(final int xmlDsigManifestCheckCode) {
+ this.xmlDsigManifestCheckCode = xmlDsigManifestCheckCode;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * setXmlDsigSubjectName(java.lang .String)
+ */
+ public void setXmlDsigSubjectName(final String xmlDsigSubjectName) {
+ this.xmlDsigSubjectName = xmlDsigSubjectName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * isXmlDSIGManigest()
+ */
+ @Override
+ public boolean isXmlDsigManigest() {
+ return xmlDsigManigest;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * setXmlDSIGManigest(boolean)
+ */
+ public void setXmlDsigManigest(final boolean xmlDsigManigest) {
+ this.xmlDsigManigest = xmlDsigManigest;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * getSignatureManifestCheckCode()
+ */
+ @Override
+ public int getSignatureManifestCheckCode() {
+ return signatureManifestCheckCode;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#
+ * setSignatureManifestCheckCode( int)
+ */
+ public void setSignatureManifestCheckCode(final int signatureManifestCheckCode) {
+ this.signatureManifestCheckCode = signatureManifestCheckCode;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java
deleted file mode 100644
index e581394b..00000000
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-import org.joda.time.DateTime;
-import org.joda.time.format.ISODateTimeFormat;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.lang.NonNull;
-import org.w3c.dom.Element;
-
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceParserException;
-import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyXMLSignatureResponse;
-import at.gv.egovernment.moaspss.util.Constants;
-import at.gv.egovernment.moaspss.util.DOMUtils;
-import at.gv.egovernment.moaspss.util.XPathUtils;
-import iaik.utils.Base64InputStream;
-import iaik.x509.X509Certificate;
-
-
-public class VerifyXMLSignatureResponseParser {
- private static final Logger log = LoggerFactory.getLogger(VerifyXMLSignatureResponseParser.class);
-
- //
- // XPath namespace prefix shortcuts
- //
- /** Xpath prefix for reaching MOA Namespaces */
- private static final String MOA = Constants.MOA_PREFIX + ":";
- /** Xpath prefix for reaching DSIG Namespaces */
- private static final String DSIG = Constants.DSIG_PREFIX + ":";
- /** Xpath expression to the root element */
- private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/";
-
- /** Xpath expression to the X509SubjectName element */
- private static final String DSIG_SUBJECT_NAME_XPATH =
- ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
- DSIG + "X509SubjectName";
- /** Xpath expression to the X509Certificate element */
- private static final String DSIG_X509_CERTIFICATE_XPATH =
- ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
- DSIG + "X509Certificate";
- /** Xpath expression to the PublicAuthority element */
- private static final String PUBLIC_AUTHORITY_XPATH =
- ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
- MOA + "PublicAuthority";
- /** Xpath expression to the PublicAuthorityCode element */
- private static final String PUBLIC_AUTHORITY_CODE_XPATH =
- PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code";
- /** Xpath expression to the QualifiedCertificate element */
- private static final String QUALIFIED_CERTIFICATE_XPATH =
- ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" +
- MOA + "QualifiedCertificate";
-
- /** Xpath expression to the SignatureCheckCode element */
- private static final String SIGNATURE_CHECK_CODE_XPATH =
- ROOT + MOA + "SignatureCheck/" + MOA + "Code";
- /** Xpath expression to the XMLDSIGManifestCheckCode element */
- private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH =
- ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code";
- /** Xpath expression to the SignatureManifestCheckCode element */
- private static final String SIGNATURE_MANIFEST_CHECK_CODE_XPATH =
- ROOT + MOA + "SignatureManifestCheck/" + MOA + "Code";
- /** Xpath expression to the CertificateCheckCode element */
- private static final String CERTIFICATE_CHECK_CODE_XPATH =
- ROOT + MOA + "CertificateCheck/" + MOA + "Code";
-
- private static final String SIGNING_TIME_XPATH =
- ROOT + MOA + "SigningTime";
-
-
- /** This is the root element of the XML-Document provided by the Security Layer Card*/
- private Element verifyXMLSignatureResponse;
-
- /**
- * Constructor for VerifyXMLSignatureResponseParser.
- * A DOM-representation of the incoming String will be created
- * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as String
- * @throws MOASigServiceParserException on any parsing error
- */
- public VerifyXMLSignatureResponseParser(String xmlResponse) throws MOASigServiceParserException {
- try {
- final InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8"));
- verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(s);
-
- } catch (final Throwable t) {
- log.warn("Can not parse MOA-Sig response." , t);
- throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t);
-
- }
- }
-
- /**
- * Constructor for VerifyXMLSignatureResponseParser.
- * A DOM-representation of the incoming Inputstream will be created
- * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
- * @throws MOASigServiceParserException on any parsing error
- */
- public VerifyXMLSignatureResponseParser(InputStream xmlResponse) throws MOASigServiceParserException {
- try {
- verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse);
-
- } catch (final Throwable t) {
- log.warn("Can not parse MOA-Sig response." , t);
- throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t);
-
- }
- }
-
- /**
- * Constructor for VerifyXMLSignatureResponseParser.
- * The incoming Element will be used for further operations
- * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as Element
- */
- public VerifyXMLSignatureResponseParser(Element xmlResponse) {
- verifyXMLSignatureResponse =xmlResponse;
-
- }
-
-/**
- * Parse MOA-Sig signatur-verification result into {@link IXMLSignatureVerificationResponse}
- *
- * @return {@link IXMLSignatureVerificationResponse}
- * @throws MOASigServiceException on any parsing error
- */
- @NonNull
- public IXMLSignatureVerificationResponse parseData() throws MOASigServiceException {
- try {
- final VerifyXMLSignatureResponse respData = new VerifyXMLSignatureResponse();
- respData.setXmlDsigSubjectName(XPathUtils.getElementValue(verifyXMLSignatureResponse,DSIG_SUBJECT_NAME_XPATH,""));
- final Element e = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,QUALIFIED_CERTIFICATE_XPATH);
- respData.setQualifiedCertificate(e!=null);
-
- final Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(XPathUtils.getElementValue(
- verifyXMLSignatureResponse,DSIG_X509_CERTIFICATE_XPATH,"").getBytes("UTF-8")),true);
-
- respData.setX509CertificateEncoded(new X509Certificate(in).getEncoded());
-
- final Element publicAuthority = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_XPATH);
- respData.setPublicAuthority(publicAuthority != null);
- respData.setPublicAuthorityCode(XPathUtils.getElementValue(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_CODE_XPATH,""));
- respData.setSignatureCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_CHECK_CODE_XPATH,"")).intValue());
-
- final String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,XMLDSIG_MANIFEST_CHECK_CODE_XPATH,null);
- if (xmlDsigCheckCode!=null) {
- respData.setXmlDSIGManigest(true);
- respData.setXmlDSIGManifestCheckCode(new Integer(xmlDsigCheckCode).intValue());
-
- } else {
- respData.setXmlDSIGManigest(false);
-
- }
-
- final String signatureManifestCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_MANIFEST_CHECK_CODE_XPATH,null);
- if (signatureManifestCheckCode != null) {
- respData.setSignatureManifestCheckCode(new Integer(signatureManifestCheckCode).intValue());
-
- }
- respData.setCertificateCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,CERTIFICATE_CHECK_CODE_XPATH,"")).intValue());
-
- final String signingTimeElement = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNING_TIME_XPATH,"");
- if (signingTimeElement != null && !signingTimeElement.isEmpty()) {
- final DateTime datetime = ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(signingTimeElement);
- respData.setSigningDateTime(datetime.toDate());
-
- }
-
- return respData;
-
- } catch (final Throwable t) {
- log.warn("Can not parse MOA-Sig response." , t);
- throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t);
- }
-
- }
-
-
-}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java
new file mode 100644
index 00000000..231cb94f
--- /dev/null
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java
@@ -0,0 +1,193 @@
+package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.joda.time.DateTime;
+import org.joda.time.format.ISODateTimeFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.lang.NonNull;
+import org.w3c.dom.Element;
+
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceParserException;
+import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyXmlSignatureResponse;
+import at.gv.egovernment.moaspss.util.Constants;
+import at.gv.egovernment.moaspss.util.DOMUtils;
+import at.gv.egovernment.moaspss.util.XPathUtils;
+import iaik.utils.Base64InputStream;
+import iaik.x509.X509Certificate;
+
+public class VerifyXmlSignatureResponseParser {
+ private static final Logger log = LoggerFactory.getLogger(VerifyXmlSignatureResponseParser.class);
+
+ //
+ // XPath namespace prefix shortcuts
+ //
+ /** Xpath prefix for reaching MOA Namespaces. */
+ private static final String MOA = Constants.MOA_PREFIX + ":";
+ /** Xpath prefix for reaching DSIG Namespaces. */
+ private static final String DSIG = Constants.DSIG_PREFIX + ":";
+ /** Xpath expression to the root element. */
+ private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/";
+
+ /** Xpath expression to the X509SubjectName element. */
+ private static final String DSIG_SUBJECT_NAME_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + DSIG + "X509SubjectName";
+ /** Xpath expression to the X509Certificate element. */
+ private static final String DSIG_X509_CERTIFICATE_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + DSIG + "X509Certificate";
+ /** Xpath expression to the PublicAuthority element. */
+ private static final String PUBLIC_AUTHORITY_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + MOA + "PublicAuthority";
+ /** Xpath expression to the PublicAuthorityCode element. */
+ private static final String PUBLIC_AUTHORITY_CODE_XPATH =
+ PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code";
+ /** Xpath expression to the QualifiedCertificate element. */
+ private static final String QUALIFIED_CERTIFICATE_XPATH =
+ ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + MOA + "QualifiedCertificate";
+
+ /** Xpath expression to the SignatureCheckCode element. */
+ private static final String SIGNATURE_CHECK_CODE_XPATH =
+ ROOT + MOA + "SignatureCheck/" + MOA + "Code";
+ /** Xpath expression to the XMLDSIGManifestCheckCode element. */
+ private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH =
+ ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code";
+ /** Xpath expression to the SignatureManifestCheckCode element. */
+ private static final String SIGNATURE_MANIFEST_CHECK_CODE_XPATH =
+ ROOT + MOA + "SignatureManifestCheck/" + MOA + "Code";
+ /** Xpath expression to the CertificateCheckCode element. */
+ private static final String CERTIFICATE_CHECK_CODE_XPATH =
+ ROOT + MOA + "CertificateCheck/" + MOA + "Code";
+
+ private static final String SIGNING_TIME_XPATH = ROOT + MOA + "SigningTime";
+
+ /**
+ * This is the root element of the XML-Document provided by the Security Layer
+ * Card.
+ */
+ private Element verifyXmlSignatureResponse;
+
+ /**
+ * Constructor for VerifyXMLSignatureResponseParser. A DOM-representation of the
+ * incoming String will be created
+ *
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as String
+ * @throws MoaSigServiceParserException on any parsing error
+ */
+ public VerifyXmlSignatureResponseParser(final String xmlResponse)
+ throws MoaSigServiceParserException {
+ try {
+ final InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8"));
+ verifyXmlSignatureResponse = DOMUtils.parseXmlValidating(s);
+
+ } catch (final Throwable t) {
+ log.warn("Can not parse MOA-Sig response.", t);
+ throw new MoaSigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t);
+
+ }
+ }
+
+ /**
+ * Constructor for VerifyXMLSignatureResponseParser. A DOM-representation of the
+ * incoming Inputstream will be created
+ *
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as InputStream
+ * @throws MoaSigServiceParserException on any parsing error
+ */
+ public VerifyXmlSignatureResponseParser(final InputStream xmlResponse)
+ throws MoaSigServiceParserException {
+ try {
+ verifyXmlSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse);
+
+ } catch (final Throwable t) {
+ log.warn("Can not parse MOA-Sig response.", t);
+ throw new MoaSigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t);
+
+ }
+ }
+
+ /**
+ * Constructor for VerifyXMLSignatureResponseParser. The incoming Element will
+ * be used for further operations
+ *
+ * @param xmlResponse <code>&lt;InfoboxReadResponse&gt;</code> as Element
+ */
+ public VerifyXmlSignatureResponseParser(final Element xmlResponse) {
+ verifyXmlSignatureResponse = xmlResponse;
+
+ }
+
+ /**
+ * Parse MOA-Sig signatur-verification result into
+ * {@link IXmlSignatureVerificationResponse}.
+ *
+ * @return {@link IXmlSignatureVerificationResponse}
+ * @throws MoaSigServiceException on any parsing error
+ */
+ @NonNull
+ public IXmlSignatureVerificationResponse parseData() throws MoaSigServiceException {
+ try {
+ final VerifyXmlSignatureResponse respData = new VerifyXmlSignatureResponse();
+ respData.setXmlDsigSubjectName(
+ XPathUtils.getElementValue(verifyXmlSignatureResponse, DSIG_SUBJECT_NAME_XPATH, ""));
+ final Element e = (Element) XPathUtils.selectSingleNode(verifyXmlSignatureResponse,
+ QUALIFIED_CERTIFICATE_XPATH);
+ respData.setQualifiedCertificate(e != null);
+
+ final Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(
+ XPathUtils.getElementValue(verifyXmlSignatureResponse, DSIG_X509_CERTIFICATE_XPATH, "")
+ .getBytes("UTF-8")),
+ true);
+
+ respData.setX509CertificateEncoded(new X509Certificate(in).getEncoded());
+
+ final Element publicAuthority =
+ (Element) XPathUtils.selectSingleNode(verifyXmlSignatureResponse, PUBLIC_AUTHORITY_XPATH);
+ respData.setPublicAuthority(publicAuthority != null);
+ respData.setPublicAuthorityCode(
+ XPathUtils.getElementValue(verifyXmlSignatureResponse, PUBLIC_AUTHORITY_CODE_XPATH, ""));
+ respData.setSignatureCheckCode(Integer.parseInt(
+ XPathUtils.getElementValue(verifyXmlSignatureResponse, SIGNATURE_CHECK_CODE_XPATH, "")));
+
+ final String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXmlSignatureResponse,
+ XMLDSIG_MANIFEST_CHECK_CODE_XPATH, null);
+ if (xmlDsigCheckCode != null) {
+ respData.setXmlDsigManigest(true);
+ respData.setXmlDsigManifestCheckCode(Integer.parseInt(xmlDsigCheckCode));
+
+ } else {
+ respData.setXmlDsigManigest(false);
+
+ }
+
+ final String signatureManifestCheckCode = XPathUtils
+ .getElementValue(verifyXmlSignatureResponse, SIGNATURE_MANIFEST_CHECK_CODE_XPATH, null);
+ if (signatureManifestCheckCode != null) {
+ respData.setSignatureManifestCheckCode(Integer.parseInt(signatureManifestCheckCode));
+
+ }
+ respData.setCertificateCheckCode(Integer.parseInt(
+ XPathUtils.getElementValue(verifyXmlSignatureResponse, CERTIFICATE_CHECK_CODE_XPATH, "")));
+
+ final String signingTimeElement =
+ XPathUtils.getElementValue(verifyXmlSignatureResponse, SIGNING_TIME_XPATH, "");
+ if (signingTimeElement != null && !signingTimeElement.isEmpty()) {
+ final DateTime datetime =
+ ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(signingTimeElement);
+ respData.setSigningDateTime(datetime.toDate());
+
+ }
+
+ return respData;
+
+ } catch (final Throwable t) {
+ log.warn("Can not parse MOA-Sig response.", t);
+ throw new MoaSigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t);
+ }
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
index ebc25602..2f0ae67f 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -1 +1 @@
-at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MOASigSpringResourceProvider \ No newline at end of file
+at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MoaSigSpringResourceProvider \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml
index 60b75f3c..c5e05853 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml
+++ b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml
@@ -1,25 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
- <context:annotation-config />
+ <context:annotation-config />
+
+ <bean id="moaSigInitializer"
+ class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MoaSigInitializer" />
+
+ <bean id="moaSigVerifyService"
+ class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureVerificationService"
+ depends-on="moaSigInitializer" />
+
+ <bean id="moaSigCreateService"
+ class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureCreationService"
+ depends-on="moaSigInitializer" />
- <bean id="moaSigInitializer"
- class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MoaSigInitializer" />
-
- <bean id="moaSigVerifyService"
- class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureVerificationService"
- depends-on="moaSigInitializer" />
-
- <bean id="moaSigCreateService"
- class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureCreationService"
- depends-on="moaSigInitializer" />
-
</beans> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java b/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java
index 7b9e2748..11c84ec0 100644
--- a/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java
+++ b/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java
@@ -6,54 +6,65 @@ import java.text.MessageFormat;
public class MavenArtifactInstaller {
- public static final String MVN_INSTALL_PATH = "F:\\local_work\\program\\apache-maven-3.5.2-bin\\bin\\";
- public static final String CONFIG = "/settings.xml";
- public static final String REPO_SCAN_PATH = "/repository/iaik/prod";
-
- public static final String GROUP = "iaik.prod";
- public static final String PACKAGE = "jar";
- public static final String COMMAND_TEMPLATE = "{6}mvn.cmd install:install-file -s {0} -DgroupId={1} -DartifactId={2} -Dversion={3} -Dpackaging={4} -Dfile={5}";
-
- public static void main(String[] args) {
- String currentLocation = new java.io.File( "." ).toURI().toString();
- currentLocation = currentLocation.substring("file:/".length(), currentLocation.length() - 2);
- final String settingLocation = currentLocation + CONFIG;
- final File settingsFile = new File(settingLocation);
- if (!settingsFile.exists()) {
- System.out.println("Maven settings does not exist");
- System.exit(-1);
-
- }
-
- final String pathToScan = currentLocation + REPO_SCAN_PATH;
-
- final File toScan = new File(pathToScan);
-
- int counter=0;
- for (final File dir : toScan.listFiles()) {
- final String artifactName = dir.getName();
- for (final File version : dir.listFiles()) {
- final String libVersion = version.getName();
- final String jarPath = version.getAbsolutePath() + "/" + artifactName + "-" + libVersion + ".jar";
- final File jar = new File(jarPath );
- if (jar.exists()) {
- final String mvnCommand = MessageFormat.format(COMMAND_TEMPLATE, settingsFile.getAbsoluteFile(), GROUP, artifactName, libVersion, PACKAGE, jar.getAbsolutePath(), MVN_INSTALL_PATH);
- System.out.println("Execute: " + mvnCommand);
- try {
- Runtime.getRuntime().exec(mvnCommand);
- counter++;
- } catch (final IOException e) {
- e.printStackTrace();
-
- }
-
- } else
- System.out.print("Can NOT find jar with path: " + jarPath);
-
- }
-
- }
- System.out.println("Install #" + counter + " maven artifacts");
- }
+ public static final String MVN_INSTALL_PATH =
+ "F:\\local_work\\program\\apache-maven-3.5.2-bin\\bin\\";
+ public static final String CONFIG = "/settings.xml";
+ public static final String REPO_SCAN_PATH = "/repository/iaik/prod";
+
+ public static final String GROUP = "iaik.prod";
+ public static final String PACKAGE = "jar";
+ public static final String COMMAND_TEMPLATE =
+ "{6}mvn.cmd install:install-file -s {0} -DgroupId={1} -DartifactId={2} -Dversion={3} -Dpackaging={4} -Dfile={5}";
+
+ /**
+ * Only for test-deployment of maven artifacts.
+ *
+ * @param args System parameters
+ */
+ public static void main(final String[] args) {
+ String currentLocation = new java.io.File(".").toURI().toString();
+ currentLocation = currentLocation.substring("file:/".length(), currentLocation.length() - 2);
+ final String settingLocation = currentLocation + CONFIG;
+ final File settingsFile = new File(settingLocation);
+ if (!settingsFile.exists()) {
+ System.out.println("Maven settings does not exist");
+ System.exit(-1);
+
+ }
+
+ final String pathToScan = currentLocation + REPO_SCAN_PATH;
+
+ final File toScan = new File(pathToScan);
+
+ int counter = 0;
+ for (final File dir : toScan.listFiles()) {
+ final String artifactName = dir.getName();
+ for (final File version : dir.listFiles()) {
+ final String libVersion = version.getName();
+ final String jarPath =
+ version.getAbsolutePath() + "/" + artifactName + "-" + libVersion + ".jar";
+ final File jar = new File(jarPath);
+ if (jar.exists()) {
+ final String mvnCommand =
+ MessageFormat.format(COMMAND_TEMPLATE, settingsFile.getAbsoluteFile(), GROUP,
+ artifactName, libVersion, PACKAGE, jar.getAbsolutePath(), MVN_INSTALL_PATH);
+ System.out.println("Execute: " + mvnCommand);
+ try {
+ Runtime.getRuntime().exec(mvnCommand);
+ counter++;
+ } catch (final IOException e) {
+ e.printStackTrace();
+
+ }
+
+ } else {
+ System.out.print("Can NOT find jar with path: " + jarPath);
+ }
+
+ }
+
+ }
+ System.out.println("Install #" + counter + " maven artifacts");
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml
index cf3f3df0..31110bfd 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml
+++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml
@@ -1,11 +1,13 @@
<?xml version="1.0"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.gv.egiz.eaaf</groupId>
<artifactId>eaaf_modules</artifactId>
- <version>1.0.13.2</version>
+ <version>1.1.0</version>
</parent>
<artifactId>eaaf_module_pvp2_core</artifactId>
<name>eaaf_module_pvp2_core</name>
@@ -13,74 +15,84 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
-
+
<dependencies>
- <dependency>
- <groupId>at.gv.egiz.eaaf</groupId>
- <artifactId>eaaf-core</artifactId>
- <version>${egiz.eaaf.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.opensaml</groupId>
- <artifactId>opensaml</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.opensaml</groupId>
- <artifactId>xmltooling</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.opensaml</groupId>
- <artifactId>openws</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.santuario</groupId>
- <artifactId>xmlsec</artifactId>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15on</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.owasp.esapi</groupId>
- <artifactId>esapi</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <scope>provided</scope>
- </dependency>
-
- <!-- Testing -->
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ <version>${egiz.eaaf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-saml-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-xmlsec-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml-xmlsec-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.santuario</groupId>
+ <artifactId>xmlsec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_core_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>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.4.01</version>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
-
+
<build>
<finalName>eaaf_module_pvp2_core</finalName>
-
+
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -90,25 +102,44 @@
<source>1.8</source>
<target>1.8</target>
</configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compile</goal>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
</plugin>
-
+
<!-- enable co-existence of testng and junit -->
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>${surefire.version}</version>
- <configuration>
- <threadCount>1</threadCount>
- <argLine>--add-modules java.xml.bind</argLine>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>org.apache.maven.surefire</groupId>
- <artifactId>surefire-junit47</artifactId>
- <version>${surefire.version}</version>
- </dependency>
- </dependencies>
- </plugin>
-
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
</plugins>
</build>
</project>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java
deleted file mode 100644
index c72db697..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2;
-
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-
-import at.gv.egiz.components.spring.api.SpringResourceProvider;
-
-public class PVP2SProfileCoreSpringResourceProvider implements SpringResourceProvider {
-
- @Override
- public String getName() {
- return "EAAF PVP2 S-Profile Core SpringResourceProvider";
- }
-
- @Override
- public String[] getPackagesToScan() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Resource[] getResourcesToLoad() {
- ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp.beans.xml", PVP2SProfileCoreSpringResourceProvider.class);
-
- return new Resource[] {sl20AuthConfig};
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java
deleted file mode 100644
index 3b57a7e3..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.xml.encryption.EncryptionConstants;
-import org.opensaml.xml.signature.SignatureConstants;
-
-import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions;
-import at.gv.egiz.eaaf.core.impl.data.Trible;
-
-public interface PVPConstants extends PVPAttributeDefinitions {
-
- public static final String DEFAULT_SIGNING_METHODE = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
- public static final String DEFAULT_DIGESTMETHODE = SignatureConstants.ALGO_ID_DIGEST_SHA256;
- public static final String DEFAULT_SYM_ENCRYPTION_METHODE = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256;
- public static final String DEFAULT_ASYM_ENCRYPTION_METHODE = EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP;
-
- public static final String ENTITY_CATEGORY_ATTRIBITE = "http://macedir.org/entity-category";
- public static final String EGOVTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken";
- public static final String CITIZENTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken";
-
- @Deprecated
- public static final String STORK_ATTRIBUTE_PREFIX = "http://www.stork.gov.eu/";
-
- public static final String REDIRECT = "Redirect";
- public static final String POST = "Post";
- public static final String SOAP = "Soap";
- public static final String METADATA = "Metadata";
- public static final String ATTRIBUTEQUERY = "AttributeQuery";
- public static final String SINGLELOGOUT = "SingleLogOut";
-
- /**
- *
- * Get required PVP attributes for egovtoken
- * First : PVP attribute name (OID)
- * Second: FriendlyName
- * Third: Required
- *
- */
- public static final List<Trible<String, String, Boolean>> EGOVTOKEN_PVP_ATTRIBUTES =
- Collections.unmodifiableList(new ArrayList<Trible<String, String, Boolean>>() {
- private static final long serialVersionUID = 1L;
- {
- //currently supported attributes
- add(Trible.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true));
- add(Trible.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true));
-
- //currently not supported attributes
- add(Trible.newInstance(USERID_NAME, USERID_FRIENDLY_NAME, false));
- add(Trible.newInstance(GID_NAME, GID_FRIENDLY_NAME, false));
- add(Trible.newInstance(PARTICIPANT_ID_NAME, PARTICIPANT_ID_FRIENDLY_NAME, false));
- add(Trible.newInstance(OU_GV_OU_ID_NAME, OU_GV_OU_ID_FRIENDLY_NAME, false));
- add(Trible.newInstance(OU_NAME, OU_FRIENDLY_NAME, false));
- add(Trible.newInstance(SECCLASS_NAME, SECCLASS_FRIENDLY_NAME, false));
-
-
- }
- });
-
- /**
- *
- * Get required PVP attributes for citizenToken
- * First : PVP attribute name (OID)
- * Second: FriendlyName
- * Third: Required
- *
- */
- public static final List<Trible<String, String, Boolean>> CITIZENTOKEN_PVP_ATTRIBUTES =
- Collections.unmodifiableList(new ArrayList<Trible<String, String, Boolean>>() {
- private static final long serialVersionUID = 1L;
- {
- //required attributes - eIDAS minimal-data set
- add(Trible.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true));
- add(Trible.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true));
- add(Trible.newInstance(GIVEN_NAME_NAME, GIVEN_NAME_FRIENDLY_NAME, true));
- add(Trible.newInstance(BIRTHDATE_NAME, BIRTHDATE_FRIENDLY_NAME, true));
- add(Trible.newInstance(BPK_NAME, BPK_FRIENDLY_NAME, true));
-
-
- //not required attributes
- add(Trible.newInstance(EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, false));
- add(Trible.newInstance(EID_ISSUING_NATION_NAME, EID_ISSUING_NATION_FRIENDLY_NAME, false));
- add(Trible.newInstance(EID_SECTOR_FOR_IDENTIFIER_NAME, EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_TYPE_NAME, MANDATE_TYPE_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_TYPE_OID_NAME, MANDATE_TYPE_OID_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_LEG_PER_SOURCE_PIN_NAME, MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_NAT_PER_BPK_NAME, MANDATE_NAT_PER_BPK_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_NAT_PER_GIVEN_NAME_NAME, MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_NAT_PER_FAMILY_NAME_NAME, MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_NAT_PER_BIRTHDATE_NAME, MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_LEG_PER_FULL_NAME_NAME, MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_PROF_REP_OID_NAME, MANDATE_PROF_REP_OID_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_PROF_REP_DESC_NAME, MANDATE_PROF_REP_DESC_FRIENDLY_NAME, false));
- add(Trible.newInstance(MANDATE_REFERENCE_VALUE_NAME, MANDATE_REFERENCE_VALUE_FRIENDLY_NAME, false));
-
-
-
- }
- });
-
- //constants for requested SAML2 attribtes by using own namespace
- public static final String EIDAT10_SAML_NS = "http://eid.gv.at/eID/attributes/saml-extensions";
- public static final String EIDAT10_PREFIX = "eid";
-
- public static final QName EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE =
- new QName(EIDAT10_SAML_NS, "AttributeValue", EIDAT10_PREFIX);
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java
deleted file mode 100644
index d1f619bf..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2;
-
-public class PVPEventConstants {
-
- //TODO!!!
- public static final int AUTHPROTOCOL_PVP_METADATA = 3100;
- public static final int AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST = 3101;
- public static final int AUTHPROTOCOL_PVP_RESPONSE_ASSERTION = 3105;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java
new file mode 100644
index 00000000..232e4ae9
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+public class Pvp2SProfileCoreSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "EAAF PVP2 S-Profile Core SpringResourceProvider";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource sl20AuthConfig =
+ new ClassPathResource("/eaaf_pvp.beans.xml", Pvp2SProfileCoreSpringResourceProvider.class);
+
+ return new Resource[] { sl20AuthConfig };
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java
new file mode 100644
index 00000000..69b94255
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+
+import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+
+import com.google.common.collect.ImmutableMap;
+
+public interface PvpConstants extends PvpAttributeDefinitions {
+ // module configuration parameters
+ String CONFIG_PROP_SEC_SIGNING_RSA_ALG = "pvp2.security.alg.signing.rsa";
+ String CONFIG_PROP_SEC_SIGNING_EC_ALG = "pvp2.security.alg.signing.ec";
+ String CONFIG_PROP_SEC_ENCRYPTION_DATA = "pvp2.security.alg.enc.data";
+ String CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG = "pvp2.security.alg.enc.key.rsa";
+ String CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG = "pvp2.security.alg.enc.key.ec";
+ String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = "pvp2.assertion.encryption.active";
+
+ // Default values
+ String DEFAULT_SIGNING_METHODE_RSA =
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
+ String DEFAULT_SIGNING_METHODE_EC =
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256;
+
+ String DEFAULT_DIGESTMETHODE = SignatureConstants.ALGO_ID_DIGEST_SHA256;
+
+ String DEFAULT_SYM_ENCRYPTION_METHODE =
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM;
+ String DEFAULT_ASYM_ENCRYPTION_METHODE_RSA =
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP;
+ String DEFAULT_ASYM_ENCRYPTION_METHODE_EC =
+ EncryptionConstants.ALGO_ID_KEYAGREEMENT_DH;
+
+ // PVP entity categories
+ String ENTITY_CATEGORY_ATTRIBITE = "http://macedir.org/entity-category";
+ String EGOVTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken";
+ String CITIZENTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken";
+
+ @Deprecated
+ String STORK_ATTRIBUTE_PREFIX = "http://www.stork.gov.eu/";
+
+ String REDIRECT = "Redirect";
+ String POST = "Post";
+ String SOAP = "Soap";
+ String METADATA = "Metadata";
+ String ATTRIBUTEQUERY = "AttributeQuery";
+ String SINGLELOGOUT = "SingleLogOut";
+
+ /**
+ * Get required PVP attributes for egovtoken First : PVP attribute name (OID)
+ * Second: FriendlyName Third: Required.
+ *
+ */
+ List<Triple<String, String, Boolean>> EGOVTOKEN_PVP_ATTRIBUTES =
+ Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() {
+ private static final long serialVersionUID = 1L;
+
+ {
+ // currently supported attributes
+ add(Triple.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true));
+ add(Triple.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true));
+
+ // currently not supported attributes
+ add(Triple.newInstance(USERID_NAME, USERID_FRIENDLY_NAME, false));
+ add(Triple.newInstance(GID_NAME, GID_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PARTICIPANT_ID_NAME, PARTICIPANT_ID_FRIENDLY_NAME, false));
+ add(Triple.newInstance(OU_GV_OU_ID_NAME, OU_GV_OU_ID_FRIENDLY_NAME, false));
+ add(Triple.newInstance(OU_NAME, OU_FRIENDLY_NAME, false));
+ add(Triple.newInstance(SECCLASS_NAME, SECCLASS_FRIENDLY_NAME, false));
+
+ }
+ });
+
+ /**
+ * Get required PVP attributes for citizenToken First : PVP attribute name (OID)
+ * Second: FriendlyName Third: Required.
+ *
+ */
+ List<Triple<String, String, Boolean>> CITIZENTOKEN_PVP_ATTRIBUTES =
+ Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() {
+ private static final long serialVersionUID = -5947165770657082581L;
+
+ {
+ // required attributes - eIDAS minimal-data set
+ add(Triple.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true));
+ add(Triple.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true));
+ add(Triple.newInstance(GIVEN_NAME_NAME, GIVEN_NAME_FRIENDLY_NAME, true));
+ add(Triple.newInstance(BIRTHDATE_NAME, BIRTHDATE_FRIENDLY_NAME, true));
+ add(Triple.newInstance(BPK_NAME, BPK_FRIENDLY_NAME, true));
+
+ // not required attributes
+ add(Triple.newInstance(EID_CITIZEN_EIDAS_QAA_LEVEL_NAME,
+ EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, false));
+ add(Triple.newInstance(EID_ISSUING_NATION_NAME, EID_ISSUING_NATION_FRIENDLY_NAME, false));
+ add(Triple.newInstance(EID_SECTOR_FOR_IDENTIFIER_NAME,
+ EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_TYPE_NAME, MANDATE_TYPE_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_TYPE_OID_NAME, MANDATE_TYPE_OID_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_LEG_PER_SOURCE_PIN_NAME,
+ MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME,
+ MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_NAT_PER_BPK_NAME, MANDATE_NAT_PER_BPK_FRIENDLY_NAME,
+ false));
+ add(Triple.newInstance(MANDATE_NAT_PER_GIVEN_NAME_NAME,
+ MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_NAT_PER_FAMILY_NAME_NAME,
+ MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_NAT_PER_BIRTHDATE_NAME,
+ MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_LEG_PER_FULL_NAME_NAME,
+ MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, false));
+ add(Triple.newInstance(MANDATE_PROF_REP_OID_NAME, MANDATE_PROF_REP_OID_FRIENDLY_NAME,
+ false));
+ add(Triple.newInstance(MANDATE_PROF_REP_DESC_NAME, MANDATE_PROF_REP_DESC_FRIENDLY_NAME,
+ false));
+ add(Triple.newInstance(MANDATE_REFERENCE_VALUE_NAME,
+ MANDATE_REFERENCE_VALUE_FRIENDLY_NAME, false));
+
+ }
+ });
+
+ // constants for requested SAML2 attribtes by using own namespace
+ String EIDAT10_SAML_NS = "http://eid.gv.at/eID/attributes/saml-extensions";
+ String EIDAT10_PREFIX = "eid";
+
+ QName EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE =
+ new QName(EIDAT10_SAML_NS, "AttributeValue", EIDAT10_PREFIX);
+
+ ImmutableMap<String, String> SIGNATURE_TO_DIGEST_ALGORITHM_MAP =
+ ImmutableMap.<String, String>builder()
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256, SignatureConstants.ALGO_ID_DIGEST_SHA256)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384, SignatureConstants.ALGO_ID_DIGEST_SHA384)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512, SignatureConstants.ALGO_ID_DIGEST_SHA512)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256, SignatureConstants.ALGO_ID_DIGEST_SHA256)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384, SignatureConstants.ALGO_ID_DIGEST_SHA384)
+ .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512, SignatureConstants.ALGO_ID_DIGEST_SHA512)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA256)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA384)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA512)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_256_MGF1,
+ MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_256)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_384_MGF1,
+ MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_384)
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_512_MGF1,
+ MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_512)
+
+ .build();
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java
new file mode 100644
index 00000000..41b64470
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2;
+
+public class PvpEventConstants {
+
+ // TODO!!!
+ public static final int AUTHPROTOCOL_PVP_METADATA = 3100;
+ public static final int AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST = 3101;
+ public static final int AUTHPROTOCOL_PVP_RESPONSE_ASSERTION = 3105;
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java
deleted file mode 100644
index 48b0efc5..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api;
-
-import java.util.List;
-
-import org.opensaml.saml2.metadata.ContactPerson;
-import org.opensaml.saml2.metadata.Organization;
-
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-
-public interface IPVP2BasicConfiguration {
-
- public String getIDPEntityId(String authURL) throws EAAFException;
-
- public String getIDPSSOPostService(String authURL) throws EAAFException;
-
- public String getIDPSSORedirectService(String authURL) throws EAAFException;
-
- public Object getIDPSSOSOAPService(String extractAuthURLFromRequest) throws EAAFException;
-
- public List<ContactPerson> getIDPContacts() throws EAAFException;
-
- public Organization getIDPOrganisation() throws EAAFException;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java
new file mode 100644
index 00000000..a54eb0b8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+import org.opensaml.saml.saml2.metadata.ContactPerson;
+import org.opensaml.saml.saml2.metadata.Organization;
+
+/**
+ * Basic SAML2 configuration object that provide information for SAML2 metadata.
+ *
+ * @author tlenz
+ *
+ */
+public interface IPvp2BasicConfiguration {
+
+ /**
+ * SAML2 EntityId.
+ *
+ * @param authUrl The Public-URL prefix of the application that always ends without /
+ * @return EntityId
+ * @throws EaafException In case of an error.
+ */
+ @Nonnull
+ String getIdpEntityId(@Nonnull String authUrl) throws EaafException;
+
+ /**
+ * Authentication end-point for POST-Binding in case of an IDP.
+ *
+ * @param authUrl The Public-URL prefix of the application that always ends without /
+ * @return IDP SSO endpoint
+ * @throws EaafException In case of an error.
+ */
+ @Nullable
+ String getIdpSsoPostService(@Nonnull String authUrl) throws EaafException;
+
+ /**
+ * Authentication end-point for POST-Redirect in case of an IDP.
+ *
+ * @param authUrl The Public-URL prefix of the application that always ends without /
+ * @return IDP SSO endpoint
+ * @throws EaafException In case of an error.
+ */
+ @Nullable
+ String getIdpSsoRedirectService(@Nonnull String authUrl) throws EaafException;
+
+ /**
+ * Authentication end-point for POST-SOAP in case of an IDP.
+ *
+ * @param authUrl The Public-URL prefix of the application that always ends without /
+ * @return IDP SSO endpoint
+ * @throws EaafException In case of an error.
+ */
+ @Nullable
+ String getIdpSsoSoapService(@Nonnull String authUrl) throws EaafException;
+
+ /**
+ * Contact information for SAML2 Metadata.
+ *
+ * @return SAML2 Contact object
+ * @throws EaafException In case of an error.
+ */
+ @Nonnull
+ List<ContactPerson> getIdpContacts() throws EaafException;
+
+ /**
+ * Organization information for SAML2 Metadata.
+ *
+ * @return SAML2 Organization object
+ * @throws EaafException In case of an error.
+ */
+ @Nonnull
+ Organization getIdpOrganisation() throws EaafException;
+
+ /**
+ * Get the basic {@link IConfiguration} object that was
+ * used to generate this {@link IPvp2BasicConfiguration}.
+ *
+ * @return Basic application configuration
+ */
+ @Nonnull
+ IConfiguration getBasicConfiguration();
+
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java
index 3b264b6d..83bfee84 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java
@@ -1,49 +1,40 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.api.binding;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
-import org.opensaml.common.binding.decoding.URIComparator;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.xml.security.SecurityException;
+import javax.xml.namespace.QName;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import net.shibboleth.utilities.java.support.net.URIComparator;
public interface IDecoder {
- public InboundMessageInterface decode(HttpServletRequest req,
- HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator)
- throws MessageDecodingException, SecurityException, PVP2Exception;
-
- public boolean handleDecode(String action, HttpServletRequest req);
-
- public String getSAML2BindingName();
+ InboundMessageInterface decode(HttpServletRequest req, HttpServletResponse resp,
+ IPvp2MetadataProvider metadataProvider, QName peerEntityRole, URIComparator comparator)
+ throws Pvp2Exception;
+
+ boolean handleDecode(String action, HttpServletRequest req);
+
+ String getSaml2BindingName();
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java
index ec400e7a..5a8bc4fb 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java
@@ -1,75 +1,68 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.api.binding;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.xml.security.SecurityException;
-import org.opensaml.xml.security.credential.Credential;
-
import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.security.SecurityException;
public interface IEncoder {
-
- /**
- *
- * @param req The http request
- * @param resp The http response
- * @param request The SAML2 request object
- * @param targetLocation URL, where the request should be transmit
- * @param relayState token for session handling
- * @param credentials Credential to sign the request object
- * @param pendingReq Internal MOA-ID request object that contains session-state informations but never null
- * @throws MessageEncodingException
- * @throws SecurityException
- * @throws PVP2Exception
- */
- public void encodeRequest(HttpServletRequest req,
- HttpServletResponse resp, RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException, PVP2Exception;
-
- /**
- * Encoder SAML Response
- * @param req The http request
- * @param resp The http response
- * @param response The SAML2 repsonse object
- * @param targetLocation URL, where the request should be transmit
- * @param relayState token for session handling
- * @param credentials Credential to sign the response object
- * @param pendingReq Internal MOA-ID request object that contains session-state informations but never null
- * @throws MessageEncodingException
- * @throws SecurityException
- */
- public void encodeRespone(HttpServletRequest req,
- HttpServletResponse resp, StatusResponseType response, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException, PVP2Exception;
+
+ /**
+ * SAML2 Request encoder.
+ *
+ * @param req The http request
+ * @param resp The http response
+ * @param request The SAML2 request object
+ * @param targetLocation URL, where the request should be transmit
+ * @param relayState token for session handling
+ * @param credentials Credential to sign the request object
+ * @param pendingReq Internal MOA-ID request object that contains
+ * session-state informations but never null
+ * @throws Pvp2Exception In case of an error
+ */
+ void encodeRequest(HttpServletRequest req, HttpServletResponse resp,
+ RequestAbstractType request, String targetLocation, String relayState, EaafX509Credential credentials,
+ IRequest pendingReq) throws Pvp2Exception;
+
+ /**
+ * Encoder SAML Response.
+ *
+ * @param req The http request
+ * @param resp The http response
+ * @param response The SAML2 repsonse object
+ * @param targetLocation URL, where the request should be transmit
+ * @param relayState token for session handling
+ * @param credentials Credential to sign the response object
+ * @param pendingReq Internal MOA-ID request object that contains
+ * session-state informations but never null
+ * @throws SecurityException In case of an error
+ */
+ void encodeResponse(HttpServletRequest req, HttpServletResponse resp,
+ StatusResponseType response, String targetLocation, String relayState, EaafX509Credential credentials,
+ IRequest pendingReq) throws Pvp2Exception;
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java
new file mode 100644
index 00000000..95070167
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java
@@ -0,0 +1,42 @@
+package at.gv.egiz.eaaf.modules.pvp2.api.credential;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.x509.X509Credential;
+
+public interface EaafX509Credential extends X509Credential {
+
+ /**
+ * Get the signature algorithm that has to be used with this credential.
+ *
+ * @return Signature-algorithm identifier
+ */
+ @Nonnull
+ String getSignatureAlgorithmForSigning();
+
+ /**
+ * Set the signature algorithm that has to be used with this credential.
+ *
+ * @param sigAlg Signature-algorithm identifier
+ */
+ void setSignatureAlgorithmForSigning(@Nonnull String sigAlg);
+
+
+ /**
+ * Get the key-encryption algorithm that has to be used with this credential
+ * in case of data-encryption operations.
+ *
+ * @return Key-encryption algorithm-identifier
+ */
+ @Nonnull
+ String getKeyEncryptionAlgorithmForDataEncryption();
+
+ /**
+ * Set the key-encryption algorithm that has to be used with this credential
+ * in case of data-encryption operations.
+ *
+ * @param sigAlg Key-encryption algorithm-identifier
+ */
+ void setKeyEncryptionAlgorithmForDataEncryption(@Nonnull String sigAlg);
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java
index 416672a1..e5b253a2 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java
@@ -1,42 +1,34 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.api.message;
import org.w3c.dom.Element;
-/**
- * @author tlenz
- *
- */
public interface InboundMessageInterface {
-
- public String getRelayState();
- public String getEntityID();
- public boolean isVerified();
- public Element getInboundMessage();
-
+
+ String getRelayState();
+
+ String getEntityID();
+
+ boolean isVerified();
+
+ Element getInboundMessage();
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java
deleted file mode 100644
index c041ec72..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.metadata.ContactPerson;
-import org.opensaml.saml2.metadata.Organization;
-import org.opensaml.saml2.metadata.RequestedAttribute;
-import org.opensaml.xml.security.credential.Credential;
-
-import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
-
-/**
- * @author tlenz
- *
- */
-public interface IPVPMetadataBuilderConfiguration {
-
-
- /**
- * Defines a unique name for this PVP Service-provider, which is used for logging
- *
- * @return
- */
- public String getSPNameForLogging();
-
- /**
- * Set metadata valid area
- *
- * @return valid until in hours [h]
- */
- public int getMetadataValidUntil();
-
- /**
- * Build a SAML2 Entities element as metadata root element
- *
- * @return true, if the metadata should start with entities element
- */
- public boolean buildEntitiesDescriptorAsRootElement();
-
- /**
- *
- *
- * @return true, if an IDP SSO-descriptor element should be generated
- */
- public boolean buildIDPSSODescriptor();
-
- /**
- *
- *
- * @return true, if an SP SSO-descriptor element should be generated
- */
- public boolean buildSPSSODescriptor();
-
- /**
- * Set the PVP entityID for this SAML2 metadata.
- * The entityID must be an URL and must be start with the public-URL prefix of the server
- *
- * @return PVP entityID postfix as String
- */
- public String getEntityID();
-
- /**
- * Set a friendlyName for this PVP entity
- *
- * @return
- */
- public String getEntityFriendlyName();
-
- /**
- * Set the contact information for this metadata entity
- *
- * @return
- */
- public List<ContactPerson> getContactPersonInformation();
-
- /**
- * Set organisation information for this metadata entity
- *
- * @return
- */
- public Organization getOrgansiationInformation();
-
-
- /**
- * Set the credential for metadata signing
- *
- * @return
- * @throws CredentialsNotAvailableException
- */
- public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException;
-
- /**
- * Set the credential for request/response signing
- * IDP metadata: this credential is used for SAML2 response signing
- * SP metadata: this credential is used for SAML2 response signing
- *
- * @return
- * @throws CredentialsNotAvailableException
- */
- public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException;
-
- /**
- * Set the credential for response encryption
- *
- * @return
- * @throws CredentialsNotAvailableException
- */
- public Credential getEncryptionCredentials() throws CredentialsNotAvailableException;
-
- /**
- * Set the IDP Post-Binding URL for WebSSO
- *
- * @return
- */
- public String getIDPWebSSOPostBindingURL();
-
- /**
- * Set the IDP Redirect-Binding URL for WebSSO
- *
- * @return
- */
- public String getIDPWebSSORedirectBindingURL();
-
- /**
- * Set the IDP Post-Binding URL for Single LogOut
- *
- * @return
- */
- public String getIDPSLOPostBindingURL();
-
- /**
- * Set the IDP Redirect-Binding URL for Single LogOut
- *
- * @return
- */
- public String getIDPSLORedirectBindingURL();
-
- /**
- * Set the SP Post-Binding URL for for the Assertion-Consumer Service
- *
- * @return
- */
- public String getSPAssertionConsumerServicePostBindingURL();
-
- /**
- * Set the SP Redirect-Binding URL for the Assertion-Consumer Service
- *
- * @return
- */
- public String getSPAssertionConsumerServiceRedirectBindingURL();
-
- /**
- * Set the SP Post-Binding URL for Single LogOut
- *
- * @return
- */
- public String getSPSLOPostBindingURL();
-
- /**
- * Set the SP Redirect-Binding URL for Single LogOut
- *
- * @return
- */
- public String getSPSLORedirectBindingURL();
-
- /**
- * Set the SP SOAP-Binding URL for Single LogOut
- *
- * @return
- */
- public String getSPSLOSOAPBindingURL();
-
-
- /**
- * Set all SAML2 attributes which could be provided by this IDP
- *
- * @return
- */
- public List<Attribute> getIDPPossibleAttributes();
-
- /**
- * Set all nameID types which could be provided by this IDP
- *
- * @return a List of SAML2 nameID types
- */
- public List<String> getIDPPossibleNameITTypes();
-
- /**
- * Set all SAML2 attributes which are required by the SP
- *
- * @return
- */
- public Collection<RequestedAttribute> getSPRequiredAttributes();
-
- /**
- * Set all nameID types which allowed from the SP
- *
- * @return a List of SAML2 nameID types
- */
- public List<String> getSPAllowedNameITTypes();
-
- /**
- * Set the 'wantAssertionSigned' attribute in SP metadata
- *
- * @return
- */
- public boolean wantAssertionSigned();
-
- /**
- * Set the 'wantAuthnRequestSigned' attribute
- *
- * @return
- */
- public boolean wantAuthnRequestSigned();
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java
deleted file mode 100644
index be36a878..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
-
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-
-public interface IPVPMetadataConfigurationFactory {
-
- public IPVPMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authURL, AbstractCredentialProvider pvpIDPCredentials);
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java
deleted file mode 100644
index f5c6a35a..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
-
-import java.util.List;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.xml.XMLObject;
-
-public interface IPVPMetadataProvider extends MetadataProvider {
-
- boolean requireValidMetadata();
-
- void setRequireValidMetadata(boolean requireValidMetadata);
-
- MetadataFilter getMetadataFilter();
-
- void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException;
-
- XMLObject getMetadata() throws MetadataProviderException;
-
- EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws MetadataProviderException;
-
- EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException;
-
- List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException;
-
- RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol) throws MetadataProviderException;
-
-} \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
new file mode 100644
index 00000000..2f058af8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+public interface IPvp2MetadataProvider extends ExtendedRefreshableMetadataResolver {
+
+ /**
+ * Get a SAML2 EntityDescriptor with an EntityId from metadata provider.
+ *
+ * @param entityID Unique EntityId of the application
+ * @return SAML2 {@link EntityDescriptor}
+ * @throws ResolverException In case of an internal resolver error.
+ */
+ @Nullable
+ EntityDescriptor getEntityDescriptor(@Nonnull String entityID) throws ResolverException;
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java
new file mode 100644
index 00000000..8e5eb715
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java
@@ -0,0 +1,22 @@
+package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
+
+import javax.annotation.Nonnull;
+
+import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing;
+
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+
+public interface IPvpAddableChainingMetadataProvider {
+
+ /**
+ * Manually add a metadata resolver into a chaining metadata provider.
+ * <br>
+ * <b>If the chaining metadata provider also implements
+ * {@link IGarbageCollectorProcessing} manually added provider
+ * can be removed by garbage-collector process. This behavior
+ * depends on chaining metadata-provider implementation. </b>
+ *
+ * @param resolver Metadata provider that should be added
+ */
+ void addMetadataResolverIntoChain(@Nonnull MetadataResolver resolver);
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java
new file mode 100644
index 00000000..3d9125fe
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
+
+import java.util.Collection;
+import java.util.List;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.metadata.ContactPerson;
+import org.opensaml.saml.saml2.metadata.Organization;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.security.credential.Credential;
+
+/**
+ * PVP Metadata builder configuration.
+ *
+ * @author tlenz
+ *
+ */
+public interface IPvpMetadataBuilderConfiguration {
+
+ /**
+ * Defines a unique name for this PVP Service-provider, which is used for
+ * logging.
+ *
+ * @return
+ */
+ String getSpNameForLogging();
+
+ /**
+ * Set metadata valid area.
+ *
+ * @return valid until in hours [h]
+ */
+ int getMetadataValidUntil();
+
+ /**
+ * Build a SAML2 Entities element as metadata root element.
+ *
+ * @return true, if the metadata should start with entities element
+ */
+ boolean buildEntitiesDescriptorAsRootElement();
+
+ /**
+ * Build an IDP SSO Descriptor.
+ *
+ * @return true, if an IDP SSO-descriptor element should be generated
+ */
+ boolean buildIdpSsoDescriptor();
+
+ /**
+ * Build a SP Descriptor.
+ *
+ * @return true, if an SP SSO-descriptor element should be generated
+ */
+ boolean buildSpSsoDescriptor();
+
+ /**
+ * Set the PVP entityID for this SAML2 metadata. The entityID must be an URL and
+ * must be start with the public-URL prefix of the server.
+ *
+ * @return PVP entityID postfix as String
+ */
+ String getEntityID();
+
+ /**
+ * Set a friendlyName for this PVP entity.
+ *
+ * @return
+ */
+ String getEntityFriendlyName();
+
+ /**
+ * Set the contact information for this metadata entity.
+ *
+ * @return
+ */
+ List<ContactPerson> getContactPersonInformation();
+
+ /**
+ * Set organisation information for this metadata entity.
+ *
+ * @return
+ */
+ Organization getOrgansiationInformation();
+
+ /**
+ * Set the credential for metadata signing.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of an error
+ */
+ EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException;
+
+ /**
+ * Set the credential for request/response signing IDP metadata: this credential
+ * is used for SAML2 response signing SP metadata: this credential is used for
+ * SAML2 response signing.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of an error
+ */
+ Credential getRequestorResponseSigningCredentials()
+ throws CredentialsNotAvailableException;
+
+ /**
+ * Set the credential for response encryption.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of an error
+ */
+ Credential getEncryptionCredentials() throws CredentialsNotAvailableException;
+
+ /**
+ * Set the IDP Post-Binding URL for WebSSO.
+ *
+ * @return
+ */
+ String getIdpWebSsoPostBindingUrl();
+
+ /**
+ * Set the IDP Redirect-Binding URL for WebSSO.
+ *
+ * @return
+ */
+ String getIdpWebSsoRedirectBindingUrl();
+
+ /**
+ * Set the IDP Post-Binding URL for Single LogOut.
+ *
+ * @return
+ */
+ String getIdpSloPostBindingUrl();
+
+ /**
+ * Set the IDP Redirect-Binding URL for Single LogOut.
+ *
+ * @return
+ */
+ String getIdpSloRedirectBindingUrl();
+
+ /**
+ * Set the SP Post-Binding URL for for the Assertion-Consumer Service.
+ *
+ * @return
+ */
+ String getSpAssertionConsumerServicePostBindingUrl();
+
+ /**
+ * Set the SP Redirect-Binding URL for the Assertion-Consumer Service.
+ *
+ * @return
+ */
+ String getSpAssertionConsumerServiceRedirectBindingUrl();
+
+ /**
+ * Set the SP Post-Binding URL for Single LogOut.
+ *
+ * @return
+ */
+ String getSpSloPostBindingUrl();
+
+ /**
+ * Set the SP Redirect-Binding URL for Single LogOut.
+ *
+ * @return
+ */
+ String getSpSloRedirectBindingUrl();
+
+ /**
+ * Set the SP SOAP-Binding URL for Single LogOut.
+ *
+ * @return
+ */
+ String getSpSloSoapBindingUrl();
+
+ /**
+ * Set all SAML2 attributes which could be provided by this IDP.
+ *
+ * @return
+ */
+ List<Attribute> getIdpPossibleAttributes();
+
+ /**
+ * Set all nameID types which could be provided by this IDP.
+ *
+ * @return a List of SAML2 nameID types
+ */
+ List<String> getIdpPossibleNameIdTypes();
+
+ /**
+ * Set all SAML2 attributes which are required by the SP.
+ *
+ * @return
+ */
+ Collection<RequestedAttribute> getSpRequiredAttributes();
+
+ /**
+ * Set all nameID types which allowed from the SP.
+ *
+ * @return a List of SAML2 nameID types
+ */
+ List<String> getSpAllowedNameIdTypes();
+
+ /**
+ * Set the 'wantAssertionSigned' attribute in SP metadata.
+ *
+ * @return
+ */
+ boolean wantAssertionSigned();
+
+ /**
+ * Set the 'wantAuthnRequestSigned' attribute.
+ *
+ * @return
+ */
+ boolean wantAuthnRequestSigned();
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java
new file mode 100644
index 00000000..fb1352ce
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider;
+
+public interface IPvpMetadataConfigurationFactory {
+
+ IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl,
+ IPvp2CredentialProvider pvpIdpCredentials);
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java
index 2f9e5fea..cc492345 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java
@@ -1,42 +1,39 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.api.metadata;
+import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver;
+
/**
+ * Metadata provider that supports dynamic refreshing on external events.
+ *
* @author tlenz
*
*/
-public interface IRefreshableMetadataProvider {
+public interface IRefreshableMetadataProvider extends RefreshableMetadataResolver {
- /**
- * Refresh a entity or load a entity in a metadata provider
- *
- * @param entityID
- * @return true, if refresh is success, otherwise false
- */
- public boolean refreshMetadataProvider(String entityID);
+ /**
+ * Refresh a entity or load a entity in a metadata provider.
+ *
+ * @param entityID EntityId
+ * @return true, if refresh is success, otherwise false
+ */
+ boolean refreshMetadataProvider(String entityID);
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java
deleted file mode 100644
index 0501a990..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api.reqattr;
-
-import java.util.List;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.common.SAMLObject;
-import org.opensaml.xml.AttributeExtensibleXMLObject;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.schema.XSBooleanValue;
-
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-
-public interface EAAFRequestedAttribute extends SAMLObject, AttributeExtensibleXMLObject , org.opensaml.saml2.metadata.RequestedAttribute{
-
- /** Element local name. */
- String DEF_LOCAL_NAME = "RequestedAttribute";
-
- /** Local name of the XSI type. */
- String TYPE_LOCAL_NAME = "RequestedAttributeAbstractType";
-
-
- /** Default element name. */
- QName DEFAULT_ELEMENT_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME,
- PVPConstants.EIDAT10_PREFIX);
-
- /** QName of the XSI type. */
- QName TYPE_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME,
- PVPConstants.EIDAT10_PREFIX);
-
-
-
- /** NAME_ATTRIB_NAME attribute name. */
- String NAME_ATTRIB_NAME = "Name";
-
- /** NAME_FORMAT_ATTRIB_NAME attribute name. */
- String NAME_FORMAT_ATTR = "NameFormat";
-
- /** IS_REQUIRED_ATTRIB_NAME attribute name. */
- String IS_REQUIRED_ATTR = "isRequired";
-
- /** FRIENDLY_NAME_ATTRIB_NAME attribute name. */
- String FRIENDLY_NAME_ATT = "FriendlyName";
-
- /** Unspecified attribute format ID. */
- String UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified";
-
- /** URI reference attribute format ID. */
- String URI_REFERENCE = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
-
- /** Basic attribute format ID. */
- String BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
-
- /**
- * Gets the name.
- *
- * @return the name
- */
- String getName();
-
- /**
- * Sets the name.
- *
- * @param name the new name
- */
- void setName(String name);
-
- /**
- * Gets the name format.
- *
- * @return the name format
- */
- String getNameFormat();
-
- /**
- * Sets the name format.
- *
- * @param nameFormat the new name format
- */
- void setNameFormat(String nameFormat);
-
- /**
- * Gets the friendly name.
- *
- * @return the friendly name
- */
- String getFriendlyName();
-
- /**
- * Sets the friendly name.
- *
- * @param friendlyName the new friendly name
- */
- void setFriendlyName(String friendlyName);
-
-/* *//**
- * Gets the checks if is required.
- *
- * @return the checks if is required
- *//*
- String isRequired();*/
-
- /**
- * Gets the checks if is required xs boolean.
- *
- * @return the checks if is required xs boolean
- */
- String getIsRequiredXSBoolean();
-
- /**
- * Sets the checks if is required.
- *
- * @param newIsRequired the new checks if is required
- */
- void setIsRequired(String newIsRequired);
-
- /**
- * Gets the attribute values.
- *
- * @return the attribute values
- */
- List<XMLObject> getAttributeValues();
-
- XSBooleanValue isRequiredXSBoolean();
-
- void setIsRequired(Boolean aBoolean);
-
- void setIsRequired(XSBooleanValue xsBooleanValue);
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java
deleted file mode 100644
index 768d5c36..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api.reqattr;
-
-import java.util.List;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.common.SAMLObject;
-
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-
-public interface EAAFRequestedAttributes extends SAMLObject {
- /** The Constant DEFAULT_ELEMENT_LOCAL_NAME. */
- String DEF_LOCAL_NAME = "RequestedAttributes";
-
- /** Default element name. */
- QName DEFAULT_ELEMENT_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME,
- PVPConstants.EIDAT10_PREFIX);
-
- /** Local name of the XSI type. */
- String TYPE_LOCAL_NAME = "RequestedAttributesType";
-
- /** QName of the XSI type. */
- QName TYPE_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME,
- PVPConstants.EIDAT10_PREFIX);
-
- /**
- * Gets the attributes.
- *
- * @return the attributes
- */
- List<EAAFRequestedAttribute> getAttributes();
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java
new file mode 100644
index 00000000..ae5fccea
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api.reqattr;
+
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+
+import org.opensaml.core.xml.AttributeExtensibleXMLObject;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.schema.XSBooleanValue;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+
+public interface EaafRequestedAttribute extends SAMLObject, AttributeExtensibleXMLObject,
+ RequestedAttribute {
+
+ /** Element local name. */
+ String DEF_LOCAL_NAME = "RequestedAttribute";
+
+ /** Local name of the XSI type. */
+ String TYPE_LOCAL_NAME = "RequestedAttributeAbstractType";
+
+ /** Default element name. */
+ QName DEFAULT_ELEMENT_NAME =
+ new QName(PvpConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX);
+
+ /** QName of the XSI type. */
+ QName TYPE_NAME =
+ new QName(PvpConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX);
+
+ /** NAME_ATTRIB_NAME attribute name. */
+ String NAME_ATTRIB_NAME = "Name";
+
+ /** NAME_FORMAT_ATTRIB_NAME attribute name. */
+ String NAME_FORMAT_ATTR = "NameFormat";
+
+ /** IS_REQUIRED_ATTRIB_NAME attribute name. */
+ String IS_REQUIRED_ATTR = "isRequired";
+
+ /** FRIENDLY_NAME_ATTRIB_NAME attribute name. */
+ String FRIENDLY_NAME_ATT = "FriendlyName";
+
+ /** Unspecified attribute format ID. */
+ String UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified";
+
+ /** URI reference attribute format ID. */
+ String URI_REFERENCE = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
+
+ /** Basic attribute format ID. */
+ String BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
+
+ /**
+ * Gets the name.
+ *
+ * @return the name
+ */
+ @Override
+ String getName();
+
+ /**
+ * Sets the name.
+ *
+ * @param name the new name
+ */
+ @Override
+ void setName(String name);
+
+ /**
+ * Gets the name format.
+ *
+ * @return the name format
+ */
+ @Override
+ String getNameFormat();
+
+ /**
+ * Sets the name format.
+ *
+ * @param nameFormat the new name format
+ */
+ @Override
+ void setNameFormat(String nameFormat);
+
+ /**
+ * Gets the friendly name.
+ *
+ * @return the friendly name
+ */
+ @Override
+ String getFriendlyName();
+
+ /**
+ * Sets the friendly name.
+ *
+ * @param friendlyName the new friendly name
+ */
+ @Override
+ void setFriendlyName(String friendlyName);
+
+ /**
+ * Gets the checks if is required xs boolean.
+ *
+ * @return the checks if is required xs boolean
+ */
+ String getIsRequiredXsBoolean();
+
+ @Override
+ void setIsRequired(Boolean aboolean);
+
+ @Override
+ void setIsRequired(XSBooleanValue xsBooleanValue);
+
+ /**
+ * Sets the checks if is required.
+ *
+ * @param newIsRequired the new checks if is required
+ */
+ void setIsRequired(String newIsRequired);
+
+ /**
+ * Gets the attribute values.
+ *
+ * @return the attribute values
+ */
+ @Override
+ List<XMLObject> getAttributeValues();
+
+ @Override
+ XSBooleanValue isRequiredXSBoolean();
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java
new file mode 100644
index 00000000..6e8d6202
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api.reqattr;
+
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+
+import org.opensaml.saml.common.SAMLObject;
+
+public interface EaafRequestedAttributes extends SAMLObject {
+ /** The Constant DEFAULT_ELEMENT_LOCAL_NAME. */
+ String DEF_LOCAL_NAME = "RequestedAttributes";
+
+ /** Default element name. */
+ QName DEFAULT_ELEMENT_NAME =
+ new QName(PvpConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX);
+
+ /** Local name of the XSI type. */
+ String TYPE_LOCAL_NAME = "RequestedAttributesType";
+
+ /** QName of the XSI type. */
+ QName TYPE_NAME =
+ new QName(PvpConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX);
+
+ /**
+ * Gets the attributes.
+ *
+ * @return the attributes
+ */
+ List<EaafRequestedAttribute> getAttributes();
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java
new file mode 100644
index 00000000..a564efb2
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java
@@ -0,0 +1,55 @@
+package at.gv.egiz.eaaf.modules.pvp2.api.utils;
+
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+
+public interface IPvp2CredentialProvider {
+
+ /**
+ * Get Credentials to sign metadata.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of a credential error
+ */
+ @Nonnull
+ EaafX509Credential getMetaDataSigningCredential() throws CredentialsNotAvailableException;
+
+ /**
+ * Get Credentials to sign SAML2 messages, like AuthnRequest, Response,
+ * Assertions as some examples.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of a credential error
+ */
+ @Nonnull
+ EaafX509Credential getMessageSigningCredential() throws CredentialsNotAvailableException;
+
+ /**
+ * Get Credentials to encrypt messages, like Assertion as example.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of a credential error
+ */
+ @Nullable
+ EaafX509Credential getMessageEncryptionCredential()
+ throws CredentialsNotAvailableException;
+
+ /**
+ * Get a List of trusted {@link X509Certificate} that are available in this
+ * KeyStore.
+ *
+ * @return List of trusted {@link X509Certificate}, or an emptry {@link List} if
+ * no certificates are available
+ * @throws CredentialsNotAvailableException In case of a KeyStore error
+ */
+ @Nonnull
+ List<X509Certificate> getTrustedCertificates()
+ throws CredentialsNotAvailableException;
+
+} \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java
index b23c230e..9f7a5980 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java
@@ -24,14 +24,15 @@ import javax.servlet.http.HttpServletRequest;
import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
/**
* SAML2 Authn. request post-processor.
*
* <p>
- * Implementations of this interface are executed before user authentication starts.
+ * Implementations of this interface are executed before user authentication
+ * starts.
* </p>
*
* @author tlenz
@@ -42,12 +43,13 @@ public interface IAuthnRequestPostProcessor {
/**
* Authn. request post-processor
*
- * @param httpReq http request
- * @param pendingReq current pending request
- * @param authReq received SAML2 authentication request
+ * @param httpReq http request
+ * @param pendingReq current pending request
+ * @param authReq received SAML2 authentication request
* @param spSsoDescriptor Metadata descriptor of the requested SP
- * @throws AuthnRequestValidatorException In case of a validation error,
- * if post processor implements additional validation
+ * @throws AuthnRequestValidatorException In case of a validation error, if post
+ * processor implements additional
+ * validation
*/
void process(HttpServletRequest httpReq, IRequest pendingReq, AuthnRequest authReq,
SPSSODescriptor spSsoDescriptor) throws AuthnRequestValidatorException;
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java
deleted file mode 100644
index 4b8ddea6..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.api.validation;
-
-import org.opensaml.saml2.core.RequestAbstractType;
-
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-
-public interface ISAMLValidator {
- public void validateRequest(RequestAbstractType request) throws EAAFException;
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java
new file mode 100644
index 00000000..9042d874
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.api.validation;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+
+public interface ISamlValidator {
+ void validateRequest(RequestAbstractType request) throws EaafException;
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java
index 189dc91e..78529e23 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java
@@ -1,48 +1,34 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-/**
- * @author tlenz
- *
- */
-public class AttributQueryException extends PVP2Exception {
+public class AttributQueryException extends Pvp2Exception {
+
+ private static final long serialVersionUID = -4302422507173728748L;
- /**
- *
- */
- private static final long serialVersionUID = -4302422507173728748L;
+ public AttributQueryException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
- public AttributQueryException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
-
- public AttributQueryException(String messageId, Object[] parameters, Throwable e) {
- super(messageId, parameters, e);
- }
+ public AttributQueryException(final String messageId, final Object[] parameters, final Throwable e) {
+ super(messageId, parameters, e);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java
index d966e4a1..cc01aa43 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java
@@ -1,45 +1,33 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.core.StatusCode;
-public class BindingNotSupportedException extends PVP2Exception {
+public class BindingNotSupportedException extends Pvp2Exception {
- public BindingNotSupportedException(String binding) {
- super("pvp2.11", new Object[] {binding});
- this.statusCodeValue = StatusCode.UNSUPPORTED_BINDING_URI;
- }
+ private static final long serialVersionUID = -7227603941387879360L;
- /**
- *
- */
- private static final long serialVersionUID = -7227603941387879360L;
+ public BindingNotSupportedException(final String binding) {
+ super("pvp2.11", new Object[] { binding });
+ this.statusCodeValue = StatusCode.UNSUPPORTED_BINDING;
+ }
-
-
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java
index e079cdef..ede00366 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java
@@ -1,48 +1,37 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+public class CredentialsNotAvailableException extends EaafException {
-public class CredentialsNotAvailableException extends EAAFException {
+ private static final long serialVersionUID = -2564476345552842599L;
- public CredentialsNotAvailableException(String messageId,
- Object[] parameters) {
- super(messageId, parameters);
- }
+ public CredentialsNotAvailableException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
- public CredentialsNotAvailableException(String messageId,
- Object[] parameters, Throwable e) {
- super(messageId, parameters, e);
- }
-
- /**
- *
- */
- private static final long serialVersionUID = -2564476345552842599L;
+ public CredentialsNotAvailableException(final String messageId, final Object[] parameters,
+ final Throwable e) {
+ super(messageId, parameters, e);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java
index 6bcddf8a..b71ab2c6 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java
@@ -1,43 +1,33 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.core.StatusCode;
-public class InvalidDateFormatException extends PVP2Exception {
+public class InvalidDateFormatException extends Pvp2Exception {
- public InvalidDateFormatException() {
- super("pvp2.02", null);
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
+ private static final long serialVersionUID = -6867976890237846085L;
- /**
- *
- */
- private static final long serialVersionUID = -6867976890237846085L;
+ public InvalidDateFormatException() {
+ super("pvp2.02", null);
+ this.statusCodeValue = StatusCode.REQUESTER;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java
deleted file mode 100644
index 1d79ae2e..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-public class InvalidPVPRequestException extends PVP2Exception {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public InvalidPVPRequestException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java
new file mode 100644
index 00000000..e13731d6
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class InvalidPvpRequestException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidPvpRequestException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java
deleted file mode 100644
index a5ff811d..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
-
-public class NameIDFormatNotSupportedException extends AuthnRequestValidatorException {
-
- public NameIDFormatNotSupportedException(String nameIDFormat) {
- super("pvp2.12", new Object[] {nameIDFormat});
- statusCodeValue = StatusCode.INVALID_NAMEID_POLICY_URI;
-
- }
-
- /**
- *
- */
- private static final long serialVersionUID = -2270762519437873336L;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java
new file mode 100644
index 00000000..57f40e8f
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public class NameIdFormatNotSupportedException extends AuthnRequestValidatorException {
+
+ private static final long serialVersionUID = -2270762519437873336L;
+
+ /**
+ * Invalid nameIdFormat in SAML2 request.
+ *
+ * @param nameIdFormat requested NameIdFormat
+ */
+ public NameIdFormatNotSupportedException(final String nameIdFormat) {
+ super("pvp2.12", new Object[] { nameIdFormat });
+ statusCodeValue = StatusCode.INVALID_NAMEID_POLICY;
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java
index e600a1c7..16dfa09f 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java
@@ -1,43 +1,33 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.core.StatusCode;
-public class NoMetadataInformationException extends PVP2Exception {
+public class NoMetadataInformationException extends Pvp2Exception {
- public NoMetadataInformationException() {
- super("pvp2.15", null);
- this.statusCodeValue = StatusCode.UNKNOWN_PRINCIPAL_URI;
- }
+ private static final long serialVersionUID = -4608068445208032193L;
- /**
- *
- */
- private static final long serialVersionUID = -4608068445208032193L;
+ public NoMetadataInformationException() {
+ super("pvp2.15", null);
+ this.statusCodeValue = StatusCode.UNKNOWN_PRINCIPAL;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java
deleted file mode 100644
index cfe4ca9d..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-
-public abstract class PVP2Exception extends EAAFException {
- //TODO:!!!!!
-
- protected String statusCodeValue = StatusCode.RESPONDER_URI;
- protected String statusMessageValue = null;
-
- public PVP2Exception(String messageId, Object[] parameters,
- Throwable wrapped) {
- super(messageId, parameters, wrapped);
- this.statusMessageValue = this.getMessage();
- }
-
- public PVP2Exception(String messageId, Object[] parameters) {
- super(messageId, parameters);
- this.statusMessageValue = this.getMessage();
- }
-
-
- public String getStatusCodeValue() {
- return (this.statusCodeValue);
- }
-
- public String getStatusMessageValue() {
- return (this.statusMessageValue);
- }
-
- /**
- *
- */
- private static final long serialVersionUID = 7669537952484421069L;
-
-
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java
deleted file mode 100644
index 379fe19f..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-public class PVP2MetadataException extends PVP2Exception {
-
- private static final long serialVersionUID = 1L;
-
- public PVP2MetadataException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
-
- public PVP2MetadataException(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/Pvp2Exception.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2Exception.java
new file mode 100644
index 00000000..54d0c5ef
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2Exception.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public abstract class Pvp2Exception extends EaafException {
+ private static final long serialVersionUID = 7669537952484421069L;
+
+ protected String statusCodeValue = StatusCode.RESPONDER;
+ protected String statusMessageValue = null;
+
+ public Pvp2Exception(final String messageId, final Object[] parameters, final Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ this.statusMessageValue = this.getMessage();
+ }
+
+ public Pvp2Exception(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ this.statusMessageValue = this.getMessage();
+ }
+
+ public String getStatusCodeValue() {
+ return this.statusCodeValue;
+ }
+
+ public String getStatusMessageValue() {
+ return this.statusMessageValue;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java
new file mode 100644
index 00000000..0b69897b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java
@@ -0,0 +1,12 @@
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class Pvp2InternalErrorException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 496637421176810375L;
+
+ public Pvp2InternalErrorException(Throwable wrapped) {
+ super("internal.pvp.98", new Object[] { wrapped.getMessage() }, wrapped);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java
new file mode 100644
index 00000000..5ed7c99d
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class Pvp2MetadataException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public Pvp2MetadataException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ public Pvp2MetadataException(final String messageId, final Object[] parameters, final 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/QAANotAllowedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotAllowedException.java
deleted file mode 100644
index a8012d85..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotAllowedException.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-
-public class QAANotAllowedException extends PVP2Exception {
-
- public QAANotAllowedException(String qaa_auth, String qaa_request, String mode) {
- super("pvp2.17", new Object[] {qaa_auth, qaa_request, mode});
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
-
- /**
- *
- */
- private static final long serialVersionUID = -3964192953884089323L;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java
deleted file mode 100644
index 0b53ae23..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-
-public class QAANotSupportedException extends PVP2Exception {
-
- public QAANotSupportedException(String qaa) {
- super("pvp2.05", new Object[] {qaa});
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
-
- /**
- *
- */
- private static final long serialVersionUID = -3964192953884089323L;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java
new file mode 100644
index 00000000..5f109b67
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public class QaaNotAllowedException extends Pvp2Exception {
+
+ private static final long serialVersionUID = -3964192953884089323L;
+
+ public QaaNotAllowedException(final String qaaAuth, final String qaaRequest, final String mode) {
+ super("pvp2.17", new Object[] { qaaAuth, qaaRequest, mode });
+ this.statusCodeValue = StatusCode.REQUESTER;
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java
new file mode 100644
index 00000000..fce44542
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public class QaaNotSupportedException extends Pvp2Exception {
+
+ private static final long serialVersionUID = -3964192953884089323L;
+
+ public QaaNotSupportedException(final String qaa) {
+ super("pvp2.05", new Object[] { qaa });
+ this.statusCodeValue = StatusCode.REQUESTER;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java
deleted file mode 100644
index 9e35871d..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-public class SAMLMetadataSignatureException extends PVP2Exception {
-
- public SAMLMetadataSignatureException() {
- super("pvp2.25", null);
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
-
- public SAMLMetadataSignatureException(Throwable e) {
- super("pvp2.25", null, e);
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
-}
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/SamlBindingException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java
new file mode 100644
index 00000000..9f079584
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java
@@ -0,0 +1,12 @@
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class SamlBindingException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 7122051055002687486L;
+
+ public SamlBindingException(String messageId, Object[] parameters, Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java
new file mode 100644
index 00000000..56d8c4a5
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java
@@ -0,0 +1,30 @@
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+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/exception/SamlMetadataSignatureException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java
new file mode 100644
index 00000000..9ef3a673
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public class SamlMetadataSignatureException extends Pvp2MetadataException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * In case of a SAML2 metadata-signature verification error.
+ *
+ * @param metadataUrl Path metadata that should be loaded
+ * @param reason Details on error
+ *
+ */
+ public SamlMetadataSignatureException(String metadataUrl, String reason) {
+ super("internal.pvp.07", new Object[] { metadataUrl, reason });
+ this.statusCodeValue = StatusCode.REQUESTER;
+
+ }
+
+ /**
+ * In case of a SAML2 metadata-signature verification error.
+ *
+ * @param metadataUrl Path metadata that should be loaded
+ * @param reason Details on error
+ * @param e Error
+ */
+ public SamlMetadataSignatureException(String metadataUrl, String reason, final Throwable e) {
+ super("internal.pvp.07", new Object[] { metadataUrl, reason }, e);
+ this.statusCodeValue = StatusCode.REQUESTER;
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java
new file mode 100644
index 00000000..e1a5a9d9
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java
@@ -0,0 +1,17 @@
+package at.gv.egiz.eaaf.modules.pvp2.exception;
+
+public class SamlSigningException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public SamlSigningException(String messageId, Object[] parameters, Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+
+ }
+
+ public SamlSigningException(String messageId, Object[] parameters) {
+ super(messageId, parameters);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java
index f9adbf6d..14ad34a5 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java
@@ -1,56 +1,34 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-/**
- * @author tlenz
- *
- */
-public class SchemaValidationException extends PVP2Exception {
+public class SchemaValidationException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1L;
- /**
- *
- */
- private static final long serialVersionUID = 1L;
+ public SchemaValidationException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
- /**
- * @param messageId
- * @param parameters
- */
- public SchemaValidationException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
-
- /**
- * @param messageId
- * @param parameters
- */
- public SchemaValidationException(String messageId, Object[] parameters, Throwable e) {
- super(messageId, parameters, e);
- }
+ public SchemaValidationException(final String messageId, final Object[] parameters, final Throwable e) {
+ super(messageId, parameters, e);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java
index 1f1f46e5..6a39336c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java
@@ -1,62 +1,41 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.exception;
-import org.opensaml.saml2.metadata.provider.FilterException;
+import org.opensaml.saml.metadata.resolver.filter.FilterException;
-/**
- * @author tlenz
- *
- */
public class SignatureValidationException extends FilterException {
- /**
- * @param string
- */
- public SignatureValidationException(String string) {
- super(string);
-
- }
-
- /**
- * @param e
- */
- public SignatureValidationException(Exception e) {
- super(e);
- }
-
- /**
- * @param string
- * @param object
- */
- public SignatureValidationException(String string, Exception e) {
- super(string, e);
- }
-
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
+
+ public SignatureValidationException(final String string) {
+ super(string);
+
+ }
+
+ public SignatureValidationException(final Exception e) {
+ super(e);
+ }
+
+ public SignatureValidationException(final String string, final Exception e) {
+ super(string, e);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java
new file mode 100644
index 00000000..3543d85a
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java
@@ -0,0 +1,219 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
+
+import javax.xml.namespace.QName;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.messaging.context.BaseContext;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.decoder.servlet.HttpServletRequestMessageDecoder;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.encoding.SAMLMessageEncoder;
+import org.opensaml.saml.common.messaging.context.SAMLEndpointContext;
+import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.common.messaging.context.SAMLProtocolContext;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.saml.saml2.metadata.SingleSignOnService;
+import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder;
+import org.opensaml.xmlsec.SignatureSigningParameters;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+import org.opensaml.xmlsec.SignatureValidationParameters;
+import org.opensaml.xmlsec.context.SecurityParametersContext;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicates;
+import com.google.common.base.Throwables;
+import com.google.common.collect.FluentIterable;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/**
+ * Abstract Binding implements common code for SAML2 binding implementations.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public abstract class AbstractBinding {
+
+ @Autowired
+ protected IConfiguration basicConfig;
+
+ public abstract String getSaml2BindingName();
+
+ protected MessageContext<SAMLObject> internalMessageDecode(
+ HttpServletRequestMessageDecoder<SAMLObject> decoder,
+ String binding) throws Pvp2Exception {
+ try {
+ decoder.initialize();
+ decoder.decode();
+
+ } catch (final ComponentInitializationException e) {
+ log.warn("Internal initialization error. Reason: {}", e.getMessage());
+ throw new Pvp2InternalErrorException(e);
+
+ } catch (final MessageDecodingException e) {
+ final Optional<Throwable> pvpException = FluentIterable.from(
+ Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(Pvp2Exception.class)).first();
+
+ if (pvpException.isPresent()) {
+ throw (Pvp2Exception) pvpException.get();
+
+ } else {
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { binding, "decoding", e.getMessage() },
+ e);
+
+ }
+
+ }
+
+ return decoder.getMessageContext();
+
+ }
+
+ protected MessageContext<SAMLObject> buildBasicMessageContext(
+ SAMLMessageEncoder encoder, SignableSAMLObject response) {
+ final MessageContext<SAMLObject> messageContext = new MessageContext<>();
+ messageContext.setMessage(response);
+ encoder.setMessageContext(messageContext);
+ return messageContext;
+
+ }
+
+ protected BaseContext injectSigningInfos(EaafX509Credential credentials) throws SamlSigningException {
+ final SecurityParametersContext securityParamContext = new SecurityParametersContext();
+ final SignatureSigningParameters signingParams = new SignatureSigningParameters();
+ securityParamContext.setSignatureSigningParameters(signingParams);
+
+ signingParams.setSigningCredential(credentials);
+ signingParams.setSignatureCanonicalizationAlgorithm(
+ SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ signingParams.setSignatureReferenceCanonicalizationAlgorithm(
+ SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ signingParams.setSignatureAlgorithm(credentials.getSignatureAlgorithmForSigning());
+ signingParams.setSignatureReferenceDigestMethod(
+ Saml2Utils.getDigestAlgorithm(signingParams.getSignatureAlgorithm()));
+
+ signingParams.setKeyInfoGenerator(Saml2Utils.getKeyInfoGenerator(credentials, true));
+
+ return securityParamContext;
+
+ }
+
+ protected BaseContext injectEndpointInfos(final SignableSAMLObject response, String targetLocation) {
+ SAMLBindingSupport.setSAML2Destination(response, targetLocation);
+ final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
+ service.setBinding(getSaml2BindingName());
+ service.setLocation(targetLocation);
+ final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext();
+ final SAMLEndpointContext endpointContext = new SAMLEndpointContext();
+ endpointContext.setEndpoint(service);
+ peerEntityContext.addSubcontext(endpointContext);
+ return peerEntityContext;
+
+ }
+
+ protected void injectInboundMessageContexts(MessageContext<SAMLObject> messageContext,
+ IPvp2MetadataProvider metadataProvider, QName peerEntityRole) throws Pvp2InternalErrorException {
+ final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext();
+ peerEntityContext.setRole(peerEntityRole);
+ messageContext.addSubcontext(peerEntityContext);
+ messageContext.addSubcontext(new SAMLMessageInfoContext());
+
+ final SAMLProtocolContext protocolContext = new SAMLProtocolContext();
+ protocolContext.setProtocol(SAMLConstants.SAML20P_NS);
+ messageContext.addSubcontext(protocolContext);
+
+ final SecurityParametersContext securityParameterContext = new SecurityParametersContext();
+ final SignatureValidationParameters sigValParameters = new SignatureValidationParameters();
+ securityParameterContext.setSignatureValidationParameters(sigValParameters);
+ messageContext.addSubcontext(securityParameterContext);
+
+ sigValParameters.setBlacklistedAlgorithms(
+ ConfigurationService.get(SignatureValidationConfiguration.class)
+ .getBlacklistedAlgorithms());
+ sigValParameters.setSignatureTrustEngine(
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+
+ }
+
+ protected void performMessageValidation(PvpSamlMessageHandlerChain messageValidatorChain,
+ MessageContext<SAMLObject> messageContext) throws Pvp2Exception {
+ try {
+ messageValidatorChain.initialize();
+ messageValidatorChain.invoke(messageContext);
+
+ } catch (final ComponentInitializationException e) {
+ log.warn("Internal initialization error. Reason: {}", e.getMessage());
+ throw new Pvp2InternalErrorException(e);
+
+ } catch (final MessageHandlerException e) {
+ log.info("SAML message validation error. Reason: {}", e.getMessage());
+ final Optional<Throwable> pvpException = FluentIterable.from(
+ Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(Pvp2Exception.class)).first();
+
+ if (pvpException.isPresent()) {
+ throw (Pvp2Exception) pvpException.get();
+
+ } else {
+ throw new SamlMessageValidationException("internal.pvp.11",
+ new Object[] { e.getMessage() }, e);
+
+ }
+ }
+ }
+
+ protected InboundMessageInterface performMessageDecodePostProcessing(
+ MessageContext<SAMLObject> messageContext, boolean isVerified) {
+ InboundMessage msg = null;
+ if (messageContext.getMessage() instanceof RequestAbstractType) {
+ final RequestAbstractType inboundMessage =
+ (RequestAbstractType) messageContext.getMessage();
+ msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName());
+ msg.setEntityID(inboundMessage.getIssuer().getValue());
+
+ } else if (messageContext.getMessage() instanceof StatusResponseType) {
+ final StatusResponseType inboundMessage =
+ (StatusResponseType) messageContext.getMessage();
+ msg = new PvpSProfileResponse(inboundMessage);
+ msg.setEntityID(inboundMessage.getIssuer().getValue());
+
+ } else {
+ // create empty container if request type is unknown
+ msg = new InboundMessage();
+
+ }
+
+ msg.setVerified(isVerified);
+ msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext));
+
+ return msg;
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java
index 79578788..c679de20 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java
@@ -1,242 +1,237 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.SAMLObject;
-import org.opensaml.common.binding.BasicSAMLMessageContext;
-import org.opensaml.common.binding.decoding.URIComparator;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.SingleSignOnService;
-import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.security.SecurityPolicyResolver;
-import org.opensaml.ws.security.provider.BasicSecurityPolicy;
-import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
-import org.opensaml.xml.parse.BasicParserPool;
-import org.opensaml.xml.security.SecurityException;
-import org.opensaml.xml.security.credential.Credential;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
+import javax.xml.namespace.QName;
import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory;
-import at.gv.egiz.eaaf.core.api.gui.IVelocityGUIBuilderConfiguration;
+import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory;
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.HTTPPostEncoderWithOwnTemplate;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PVPSignedRequestPolicyRule;
-
-@Service("PVPPOSTBinding")
-public class PostBinding implements IDecoder, IEncoder {
- private static final Logger log = LoggerFactory.getLogger(PostBinding.class);
-
- @Autowired(required=true) IConfiguration authConfig;
- @Autowired(required=true) IVelocityGuiFormBuilder guiBuilder;
- @Autowired(required=true) IGUIBuilderConfigurationFactory guiConfigFactory;
-
- @Override
- public void encodeRequest(HttpServletRequest req, HttpServletResponse resp,
- RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
-
- try {
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
-
- //initialize POST binding encoder with template decoration
- final IVelocityGUIBuilderConfiguration guiConfig = guiConfigFactory.getSPSpecificSAML2PostConfiguration(
- pendingReq,
- "pvp_postbinding_template.html",
- authConfig.getConfigurationRootDirectory());
-
- final HTTPPostEncoderWithOwnTemplate encoder = new HTTPPostEncoderWithOwnTemplate(guiConfig, guiBuilder,
- VelocityProvider.getClassPathVelocityEngine());
-
- //set OpenSAML2 process parameter into binding context dao
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
- resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject();
- service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
- service.setLocation(targetLocation);;
-
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(request);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
-
- encoder.encode(context);
-
- } catch (final Exception e) {
- log.warn("Can not encode SAML2 request", e);
- throw new SecurityException(e);
-
- }
- }
-
- @Override
- public void encodeRespone(HttpServletRequest req, HttpServletResponse resp,
- StatusResponseType response, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
-
- try {
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
-
- log.debug("create SAML POSTBinding response");
-
- //initialize POST binding encoder with template decoration
- final IVelocityGUIBuilderConfiguration guiConfig = guiConfigFactory.getSPSpecificSAML2PostConfiguration(
- pendingReq,
- "pvp_postbinding_template.html",
- authConfig.getConfigurationRootDirectory());
- final HTTPPostEncoderWithOwnTemplate encoder = new HTTPPostEncoderWithOwnTemplate(guiConfig, guiBuilder,
- VelocityProvider.getClassPathVelocityEngine());
-
- //set OpenSAML2 process parameter into binding context dao
- final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
- resp, true);
- final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- final SingleSignOnService service = new SingleSignOnServiceBuilder()
- .buildObject();
- service.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
- service.setLocation(targetLocation);
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- // context.setOutboundMessage(authReq);
- context.setOutboundSAMLMessage(response);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
-
- encoder.encode(context);
-
- } catch (final Exception e) {
- log.warn("Can not encode SAML2 response", e);
- throw new SecurityException(e);
-
- }
- }
-
- @Override
- public InboundMessageInterface decode(HttpServletRequest req,
- HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) throws MessageDecodingException,
- SecurityException {
-
- final HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool());
- final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- messageContext
- .setInboundMessageTransport(new HttpServletRequestAdapter(req));
- //set metadata descriptor type
- if (isSPEndPoint) {
- messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
-
- } else {
- messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
- }
-
- messageContext.setMetadataProvider(metadataProvider);
-
- //set security policy context
- final BasicSecurityPolicy policy = new BasicSecurityPolicy();
- policy.getPolicyRules().add(
- new PVPSignedRequestPolicyRule(metadataProvider,
- TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider),
- messageContext.getPeerEntityRole()));
- final SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy);
- messageContext.setSecurityPolicyResolver(secResolver);
-
- decode.decode(messageContext);
-
- InboundMessage msg = null;
- if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
- final RequestAbstractType inboundMessage = (RequestAbstractType) messageContext
- .getInboundMessage();
- msg = new PVPSProfileRequest(inboundMessage, getSAML2BindingName());
- msg.setEntityID(inboundMessage.getIssuer().getValue());
-
- } else if (messageContext.getInboundMessage() instanceof StatusResponseType){
- final StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage();
- msg = new PVPSProfileResponse(inboundMessage);
- msg.setEntityID(inboundMessage.getIssuer().getValue());
-
- } else
- //create empty container if request type is unknown
- msg = new InboundMessage();
-
- if (messageContext.getPeerEntityMetadata() != null)
- msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
-
- else {
- if (StringUtils.isEmpty(msg.getEntityID()))
- log.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
- }
-
-
- msg.setVerified(true);
- msg.setRelayState(messageContext.getRelayState());
-
- return msg;
- }
-
- @Override
- public boolean handleDecode(String action, HttpServletRequest req) {
- return (req.getMethod().equals("POST") && action.equals(PVPConstants.POST));
- }
-
- @Override
- public String getSAML2BindingName() {
- return SAMLConstants.SAML2_POST_BINDING_URI;
- }
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpPostDecoder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.HttpPostEncoderWithOwnTemplate;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSamlProtocolMessageXmlSignatureSecurityHandler;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler;
+import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler;
+import org.opensaml.saml.common.binding.security.impl.ReceivedEndpointSecurityHandler;
+import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.net.URIComparator;
+
+@Slf4j
+public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {
+
+ @Autowired(required = true)
+ IConfiguration authConfig;
+ @Autowired(required = true)
+ IVelocityGuiFormBuilder guiBuilder;
+ @Autowired(required = true)
+ IGuiBuilderConfigurationFactory guiConfigFactory;
+
+ @Override
+ public void encodeRequest(final HttpServletRequest httpReq, final HttpServletResponse httpResp,
+ final RequestAbstractType request, final String targetLocation, final String relayState,
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ // initialize POST binding encoder with template decoration
+ final IVelocityGuiBuilderConfiguration guiConfig =
+ guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq,
+ "pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory());
+
+ final HttpPostEncoderWithOwnTemplate encoder = new HttpPostEncoderWithOwnTemplate(guiConfig,
+ guiBuilder);
+
+ encoder.setHttpServletResponse(httpResp);
+
+ // inject message context
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request);
+
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(request, targetLocation));
+
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ // sign SAML2 message
+ SAMLMessageSecuritySupport.signMessage(messageContext);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 Post-Binding request", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.POST, "encoding", e.getMessage() },
+ e);
+
+ }
+ }
+
+ @Override
+ public void encodeResponse(final HttpServletRequest httpReq, final HttpServletResponse httpResp,
+ final StatusResponseType response, final String targetLocation, final String relayState,
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ log.debug("create SAML POSTBinding response");
+
+ // initialize POST binding encoder with template decoration
+ final IVelocityGuiBuilderConfiguration guiConfig =
+ guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq,
+ "pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory());
+ final HttpPostEncoderWithOwnTemplate encoder =
+ new HttpPostEncoderWithOwnTemplate(guiConfig, guiBuilder);
+
+ encoder.setHttpServletResponse(httpResp);
+
+ // inject message context
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response);
+
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(response, targetLocation));
+
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ // sign SAML2 message
+ SAMLMessageSecuritySupport.signMessage(messageContext);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 Post-Binding response", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.POST, "encoding", e.getMessage() },
+ e);
+
+ }
+ }
+
+ @Override
+ public InboundMessageInterface decode(final HttpServletRequest req,
+ final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,
+ QName peerEntityRole, final URIComparator comparator)
+ throws Pvp2Exception {
+
+ final EaafHttpPostDecoder decode = new EaafHttpPostDecoder(req);
+ final MessageContext<SAMLObject> messageContext = internalMessageDecode(decode, PvpConstants.POST);
+
+ // check if PVP2 AuthnRequest is signed
+ if (!SAMLBindingSupport.isMessageSigned(messageContext)) {
+ log.info("SAML Post-Binding message contains no signature. Message will be rejected");
+ throw new InvalidPvpRequestException("internal.pvp.02", null);
+
+ }
+
+ // inject informations into message context that are required for further
+ // processing
+ injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole);
+ final PvpSamlMessageHandlerChain messageValidatorChain =
+ buildMessageValidationChain(req, comparator, metadataProvider);
+
+ log.trace("Message validation (Signature, ...) on binding-level starts ... ");
+ performMessageValidation(messageValidatorChain, messageContext);
+
+ log.trace("Message validation successful");
+ return performMessageDecodePostProcessing(messageContext, true);
+
+ }
+
+ @Override
+ public boolean handleDecode(final String action, final HttpServletRequest req) {
+ return req.getMethod().equals("POST") && action.equals(PvpConstants.POST);
+
+ }
+
+ @Override
+ public String getSaml2BindingName() {
+ return SAMLConstants.SAML2_POST_BINDING_URI;
+
+ }
+
+ private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req,
+ URIComparator comparator, IPvp2MetadataProvider metadataProvider) {
+ final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain();
+
+ final ReceivedEndpointSecurityHandler endpointSecurityHandler = new ReceivedEndpointSecurityHandler();
+ endpointSecurityHandler.setHttpServletRequest(req);
+ endpointSecurityHandler.setURIComparator(comparator);
+
+ messageValidatorChain.addHandler(new CheckMessageVersionHandler());
+ messageValidatorChain.addHandler(endpointSecurityHandler);
+ messageValidatorChain.addHandler(
+ new EaafSamlProtocolMessageXmlSignatureSecurityHandler(metadataProvider));
+ messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler());
+
+ /*
+ * TODO: maybe we add it in a later version Because: - AuthnRequest replay
+ * should not be a problem on IDP side - Response replay will be not possible,
+ * because EAAF PVP implements countermeasure based on one-time tokens for each
+ * request
+ *
+ */
+ // final MessageReplaySecurityHandler replaySecurityHandler = new
+ // MessageReplaySecurityHandler();
+ // final StorageService replayCacheStorage = null;
+ // final ReplayCache replayCache = new ReplayCache();
+ // replayCache.setId("Message replay cache");
+ // replayCache.setStrict(true);
+ // replayCache.setStorage(replayCacheStorage);
+ // replaySecurityHandler.setReplayCache(replayCache );
+ // messageValidatorChain.addHandler(replaySecurityHandler);
+
+ return messageValidatorChain;
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java
index ca9b3d98..f62f8a11 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java
@@ -1,239 +1,205 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.SAMLObject;
-import org.opensaml.common.binding.BasicSAMLMessageContext;
-import org.opensaml.common.binding.decoding.URIComparator;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder;
-import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
-import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.SingleSignOnService;
-import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.security.SecurityPolicyResolver;
-import org.opensaml.ws.security.provider.BasicSecurityPolicy;
-import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
-import org.opensaml.xml.parse.BasicParserPool;
-import org.opensaml.xml.security.SecurityException;
-import org.opensaml.xml.security.credential.Credential;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
+import javax.xml.namespace.QName;
import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap;
-import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
-import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PVPAuthRequestSignedRole;
-
-@Service("PVPRedirectBinding")
-public class RedirectBinding implements IDecoder, IEncoder {
-
- private static final Logger log = LoggerFactory.getLogger(RedirectBinding.class);
-
- public void encodeRequest(HttpServletRequest req, HttpServletResponse resp,
- RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException {
-
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
-
- log.debug("create SAML RedirectBinding response");
-
- HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
- HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
- resp, true);
- BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- SingleSignOnService service = new SingleSignOnServiceBuilder()
- .buildObject();
- service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- service.setLocation(targetLocation);
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(request);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
-
- encoder.encode(context);
- }
-
- public void encodeRespone(HttpServletRequest req, HttpServletResponse resp,
- StatusResponseType response, String targetLocation, String relayState,
- Credential credentials, IRequest pendingReq) throws MessageEncodingException, SecurityException {
-
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
-
- log.debug("create SAML RedirectBinding response");
-
- HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
- HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
- resp, true);
- BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- SingleSignOnService service = new SingleSignOnServiceBuilder()
- .buildObject();
- service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- service.setLocation(targetLocation);
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(response);
- context.setOutboundMessageTransport(responseAdapter);
- context.setRelayState(relayState);
-
- encoder.encode(context);
-
- }
-
- public InboundMessageInterface decode(HttpServletRequest req,
- HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) throws MessageDecodingException,
- SecurityException {
-
- HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(
- new BasicParserPool());
-
- BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- messageContext
- .setInboundMessageTransport(new HttpServletRequestAdapter(req));
-
- //set metadata descriptor type
- if (isSPEndPoint) {
- messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
-
- } else {
- messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
- decode.setURIComparator(comparator);
- }
-
- messageContext.setMetadataProvider(metadataProvider);
-
- SAML2HTTPRedirectDeflateSignatureRule signatureRule = new SAML2HTTPRedirectDeflateSignatureRule(
- TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
- PVPAuthRequestSignedRole signedRole = new PVPAuthRequestSignedRole();
- BasicSecurityPolicy policy = new BasicSecurityPolicy();
- policy.getPolicyRules().add(signedRole);
- policy.getPolicyRules().add(signatureRule);
- SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver(
- policy);
- messageContext.setSecurityPolicyResolver(resolver);
-
- //set metadata descriptor type
- if (isSPEndPoint)
- messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
- else
- messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
-
- try {
- decode.decode(messageContext);
-
- //check signature
- signatureRule.evaluate(messageContext);
-
- } catch (SecurityException e) {
- if (StringUtils.isEmpty(messageContext.getInboundMessageIssuer())) {
- throw e;
-
- }
-
- if (metadataProvider instanceof IRefreshableMetadataProvider) {
- log.debug("PVP2X message validation FAILED. Reload metadata for entityID: " + messageContext.getInboundMessageIssuer());
- if (!((IRefreshableMetadataProvider) metadataProvider).refreshMetadataProvider(messageContext.getInboundMessageIssuer()))
- throw e;
-
- else {
- log.trace("PVP2X metadata reload finished. Check validate message again.");
- decode.decode(messageContext);
-
- //check signature
- signatureRule.evaluate(messageContext);
-
- }
- log.trace("Second PVP2X message validation finished");
-
- } else {
- throw e;
-
- }
- }
-
- InboundMessage msg = null;
- if (messageContext.getInboundMessage() instanceof RequestAbstractType) {
- RequestAbstractType inboundMessage = (RequestAbstractType) messageContext
- .getInboundMessage();
- msg = new PVPSProfileRequest(inboundMessage, getSAML2BindingName());
-
-
- } else if (messageContext.getInboundMessage() instanceof StatusResponseType){
- StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage();
- msg = new PVPSProfileResponse(inboundMessage);
-
- } else
- //create empty container if request type is unknown
- msg = new InboundMessage();
-
- if (messageContext.getPeerEntityMetadata() != null)
- msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
-
- else
- log.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());
-
- msg.setVerified(true);
- msg.setRelayState(messageContext.getRelayState());
-
- return msg;
- }
-
- public boolean handleDecode(String action, HttpServletRequest req) {
- return ((action.equals(PVPConstants.REDIRECT) || action.equals(PVPConstants.SINGLELOGOUT))
- && req.getMethod().equals("GET"));
- }
-
- public String getSAML2BindingName() {
- return SAMLConstants.SAML2_REDIRECT_BINDING_URI;
- }
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpRedirectDeflateDecoder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSaml2HttpRedirectDeflateSignatureSecurityHandler;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler;
+import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler;
+import org.opensaml.saml.common.messaging.context.SAMLBindingContext;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.net.URIComparator;
+
+public class RedirectBinding extends AbstractBinding implements IDecoder, IEncoder {
+
+ private static final Logger log = LoggerFactory.getLogger(RedirectBinding.class);
+
+ @Override
+ public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp,
+ final RequestAbstractType request, final String targetLocation, final String relayState,
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ log.debug("create SAML RedirectBinding response");
+ final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
+ encoder.setHttpServletResponse(resp);
+
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request);
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(request, targetLocation));
+
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 Redirect-Binding request", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.REDIRECT, "encoding", e.getMessage() },
+ e);
+
+ }
+
+ }
+
+ @Override
+ public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp,
+ final StatusResponseType response, final String targetLocation, final String relayState,
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ log.debug("create SAML RedirectBinding response");
+
+ final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
+ encoder.setHttpServletResponse(resp);
+
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response);
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(response, targetLocation));
+
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 Redirect-Binding request", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.REDIRECT, "encoding", e.getMessage() },
+ e);
+
+ }
+
+ }
+
+ @Override
+ public InboundMessageInterface decode(final HttpServletRequest req,
+ final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,
+ QName peerEntityRole, final URIComparator comparator)
+ throws Pvp2Exception {
+
+ final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(req);
+ final MessageContext<SAMLObject> messageContext = internalMessageDecode(decode, PvpConstants.REDIRECT);
+
+ final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true);
+ if (!bindingContext.hasBindingSignature()) {
+ log.info("SAML Redirect-Binding message contains no signature. Message will be rejected");
+ throw new InvalidPvpRequestException("internal.pvp.02", null);
+
+ }
+
+ // inject informations into message context that are required for further
+ // processing
+ injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole);
+ final PvpSamlMessageHandlerChain messageValidatorChain =
+ buildMessageValidationChain(req, metadataProvider);
+
+ log.trace("Message validation (Signature, ...) on binding-level starts ... ");
+ performMessageValidation(messageValidatorChain, messageContext);
+
+ log.trace("Message validation successful");
+ return performMessageDecodePostProcessing(messageContext, true);
+
+ }
+
+ @Override
+ public boolean handleDecode(final String action, final HttpServletRequest req) {
+ return (action.equals(PvpConstants.REDIRECT) || action.equals(PvpConstants.SINGLELOGOUT))
+ && req.getMethod().equals("GET");
+ }
+
+ @Override
+ public String getSaml2BindingName() {
+ return SAMLConstants.SAML2_REDIRECT_BINDING_URI;
+
+ }
+
+ private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req,
+ IPvp2MetadataProvider metadataProvider) {
+ final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain();
+ final EaafSaml2HttpRedirectDeflateSignatureSecurityHandler redirectBindingSignaturHandler =
+ new EaafSaml2HttpRedirectDeflateSignatureSecurityHandler(metadataProvider);
+ redirectBindingSignaturHandler.setHttpServletRequest(req);
+
+ messageValidatorChain.addHandler(new CheckMessageVersionHandler());
+ messageValidatorChain.addHandler(redirectBindingSignaturHandler);
+ messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler());
+
+ /*
+ * TODO: maybe we add it in a later version Because: - AuthnRequest replay
+ * should not be a problem on IDP side - Response replay will be not possible,
+ * because EAAF PVP implements countermeasure based on one-time tokens for each
+ * request
+ *
+ */
+ // final MessageReplaySecurityHandler replaySecurityHandler = new
+ // MessageReplaySecurityHandler();
+ // final StorageService replayCacheStorage = null;
+ // final ReplayCache replayCache = new ReplayCache();
+ // replayCache.setId("Message replay cache");
+ // replayCache.setStrict(true);
+ // replayCache.setStorage(replayCacheStorage);
+ // replaySecurityHandler.setReplayCache(replayCache );
+ // messageValidatorChain.addHandler(replaySecurityHandler);
+
+ return messageValidatorChain;
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java
index c70060ad..49e93f0a 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java
@@ -1,172 +1,181 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
-import java.util.List;
+package at.gv.egiz.eaaf.modules.pvp2.impl.binding;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.SAMLObject;
-import org.opensaml.common.binding.BasicSAMLMessageContext;
-import org.opensaml.common.binding.decoding.URIComparator;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.ws.message.decoder.MessageDecodingException;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.soap.soap11.Envelope;
-import org.opensaml.ws.soap.soap11.decoder.http.HTTPSOAP11Decoder;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.parse.BasicParserPool;
-import org.opensaml.xml.security.SecurityException;
-import org.opensaml.xml.security.credential.Credential;
-import org.opensaml.xml.signature.SignableXMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
+import javax.xml.namespace.QName;
import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.exception.AttributQueryException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap;
-
-@Service("PVPSOAPBinding")
-public class SoapBinding implements IDecoder, IEncoder {
-
- private static final Logger log = LoggerFactory.getLogger(SoapBinding.class);
- public InboundMessageInterface decode(HttpServletRequest req,
- HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) throws MessageDecodingException,
- SecurityException, PVP2Exception {
- HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool());
- BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =
- new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- messageContext
- .setInboundMessageTransport(new HttpServletRequestAdapter(
- req));
- messageContext.setMetadataProvider(metadataProvider);
-
- //TODO: update in a futher version:
- // requires a special SignedSOAPRequestPolicyRole because
- // messageContext.getInboundMessage() is not directly signed
-
- //set security context
-// BasicSecurityPolicy policy = new BasicSecurityPolicy();
-// policy.getPolicyRules().add(
-// new MOAPVPSignedRequestPolicyRule(
-// TrustEngineFactory.getSignatureKnownKeysTrustEngine(),
-// SPSSODescriptor.DEFAULT_ELEMENT_NAME));
-// SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver(
-// policy);
-// messageContext.setSecurityPolicyResolver(resolver);
-
- //decode message
- soapDecoder.decode(messageContext);
-
- Envelope inboundMessage = (Envelope) messageContext
- .getInboundMessage();
-
- if (inboundMessage.getBody() != null) {
- List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects();
-
- if (!xmlElemList.isEmpty()) {
- SignableXMLObject attrReq = (SignableXMLObject) xmlElemList.get(0);
- PVPSProfileRequest request = new PVPSProfileRequest(attrReq, getSAML2BindingName());
-
- if (messageContext.getPeerEntityMetadata() != null)
- request.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());
-
- else if (attrReq instanceof RequestAbstractType) {
- RequestAbstractType attributeRequest = (RequestAbstractType) attrReq;
- try {
- if (StringUtils.isNotEmpty(attributeRequest.getIssuer().getValue()) &&
- metadataProvider.getRole(
- attributeRequest.getIssuer().getValue(),
- SPSSODescriptor.DEFAULT_ELEMENT_NAME) != null)
- request.setEntityID(attributeRequest.getIssuer().getValue());
-
- } catch (Exception e) {
- log.warn("No Metadata found with EntityID " + attributeRequest.getIssuer().getValue());
- }
- }
-
- request.setVerified(false);
- return request;
-
- }
- }
-
- log.error("Receive empty PVP 2.1 attributequery request.");
- throw new AttributQueryException("Receive empty PVP 2.1 attributequery request.", null);
- }
-
- public boolean handleDecode(String action, HttpServletRequest req) {
- return (req.getMethod().equals("POST") &&
- (action.equals(PVPConstants.SOAP) || action.equals(PVPConstants.ATTRIBUTEQUERY)));
- }
-
- public void encodeRequest(HttpServletRequest req, HttpServletResponse resp,
- RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException, PVP2Exception {
-
- }
-
- public void encodeRespone(HttpServletRequest req, HttpServletResponse resp,
- StatusResponseType response, String targetLocation, String relayState, Credential credentials, IRequest pendingReq)
- throws MessageEncodingException, SecurityException, PVP2Exception {
-
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
-
- HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
- HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
- resp, true);
- BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- context.setOutboundSAMLMessageSigningCredential(credentials);
- context.setOutboundSAMLMessage(response);
- context.setOutboundMessageTransport(responseAdapter);
-
- encoder.encode(context);
-
- }
-
- public String getSAML2BindingName() {
- return SAMLConstants.SAML2_SOAP11_BINDING_URI;
- }
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafMessageContextInitializationHandler;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSamlProtocolMessageXmlSignatureSecurityHandler;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler;
+import org.opensaml.saml.common.binding.impl.SAMLProtocolAndRoleHandler;
+import org.opensaml.saml.common.binding.impl.SAMLSOAPDecoderBodyHandler;
+import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler;
+import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.binding.decoding.impl.HTTPSOAP11Decoder;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPSOAP11Encoder;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.soap.messaging.context.SOAP11Context;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.net.URIComparator;
+
+@Slf4j
+public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder {
+
+ @Override
+ public InboundMessageInterface decode(final HttpServletRequest req,
+ final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,
+ QName peerEntityRole, final URIComparator comparator)
+ throws Pvp2Exception {
+
+ final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder();
+ soapDecoder.setHttpServletRequest(req);
+
+ injectMessageHandlerChain(soapDecoder, metadataProvider, peerEntityRole);
+
+ final MessageContext<SAMLObject> messageContext =
+ internalMessageDecode(soapDecoder, PvpConstants.SOAP);
+
+ // check if PVP2 AuthnRequest is signed
+ if (!SAMLBindingSupport.isMessageSigned(messageContext)) {
+ log.info("SAML Post-Binding message contains no signature. Message will be rejected");
+ throw new InvalidPvpRequestException("internal.pvp.02", null);
+
+ }
+
+ return performMessageDecodePostProcessing(messageContext, true);
+ }
+
+ private void injectMessageHandlerChain(HTTPSOAP11Decoder soapDecoder,
+ IPvp2MetadataProvider metadataProvider, QName peerEntityRole) throws Pvp2InternalErrorException {
+ try {
+ final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain();
+ messageValidatorChain.addHandler(new EaafMessageContextInitializationHandler(metadataProvider));
+ messageValidatorChain.addHandler(new SAMLSOAPDecoderBodyHandler());
+
+ final SAMLProtocolAndRoleHandler samlProtocolHandler = new SAMLProtocolAndRoleHandler();
+ samlProtocolHandler.setProtocol(SAMLConstants.SAML20P_NS);
+ samlProtocolHandler.setRole(peerEntityRole);
+ messageValidatorChain.addHandler(samlProtocolHandler);
+
+ messageValidatorChain.addHandler(new CheckMessageVersionHandler());
+ messageValidatorChain.addHandler(
+ new EaafSamlProtocolMessageXmlSignatureSecurityHandler(metadataProvider));
+ messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler());
+
+ messageValidatorChain.initialize();
+
+ soapDecoder.setBodyHandler(messageValidatorChain);
+
+ } catch (final ComponentInitializationException e) {
+ log.warn("Internal initialization error. Reason: {}", e.getMessage());
+ throw new Pvp2InternalErrorException(e);
+
+ }
+
+
+ }
+
+ @Override
+ public boolean handleDecode(final String action, final HttpServletRequest req) {
+ return req.getMethod().equals("POST")
+ && action.equals(PvpConstants.SOAP) || action.equals(PvpConstants.ATTRIBUTEQUERY);
+ }
+
+ @Override
+ public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp,
+ final RequestAbstractType request, final String targetLocation, final String relayState,
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+ throw new RuntimeException("Method not supported!!!");
+
+ }
+
+ @Override
+ public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp,
+ final StatusResponseType response, final String targetLocation, final String relayState,
+ final EaafX509Credential credentials, final IRequest pendingReq)
+ throws Pvp2Exception {
+
+ try {
+ final HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
+ encoder.setHttpServletResponse(resp);
+
+ // inject message context
+ final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response);
+
+ //inject SOAP enveloped
+ final SOAP11Context soap11Context = new SOAP11Context();
+ soap11Context.setEnvelope(Saml2Utils.buildSoap11Envelope(response));
+ messageContext.addSubcontext(soap11Context);
+
+ // inject signing context
+ messageContext.addSubcontext(injectSigningInfos(credentials));
+
+ // set endpoint url
+ messageContext.addSubcontext(injectEndpointInfos(response, targetLocation));
+
+ // set relayState of exists
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ // sign SAML2 message
+ SAMLMessageSecuritySupport.signMessage(messageContext);
+
+ // encode message
+ encoder.initialize();
+ encoder.encode();
+
+ } catch (final Exception e) {
+ log.warn("Can not encode SAML2 SOAP-Binding response", e);
+ throw new SamlBindingException("internal.pvp.95",
+ new Object[] { PvpConstants.SOAP, "encoding", e.getMessage() },
+ e);
+
+ }
+ }
+
+ @Override
+ public String getSaml2BindingName() {
+ return SAMLConstants.SAML2_SOAP11_BINDING_URI;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java
index c38b04bd..bf201803 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java
@@ -1,121 +1,148 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.core.AttributeValue;
-import org.opensaml.xml.Configuration;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.schema.XSInteger;
-import org.opensaml.xml.schema.XSString;
-import org.opensaml.xml.schema.impl.XSIntegerBuilder;
-import org.opensaml.xml.schema.impl.XSStringBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSInteger;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.core.xml.schema.impl.XSIntegerBuilder;
+import org.opensaml.core.xml.schema.impl.XSStringBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
+/**
+ * Build all attributes from PVP2 citizen-token.
+ *
+ * @author tlenz
+ *
+ */
public class CitizenTokenBuilder {
- public static XMLObject buildAttributeStringValue(String value) {
- XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
- XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
- stringValue.setValue(value);
- return stringValue;
- }
-
- public static XMLObject buildAttributeIntegerValue(int value) {
- XSIntegerBuilder integerBuilder = (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);
- XSInteger integerValue = integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
- integerValue.setValue(value);
- return integerValue;
- }
-
- public static Attribute buildStringAttribute(String friendlyName,
- String name, String value) {
- Attribute attribute =
- SAML2Utils.createSAMLObject(Attribute.class);
- attribute.setFriendlyName(friendlyName);
- attribute.setName(name);
- attribute.getAttributeValues().add(buildAttributeStringValue(value));
- return attribute;
- }
-
- public static Attribute buildIntegerAttribute(String friendlyName,
- String name, int value) {
- Attribute attribute =
- SAML2Utils.createSAMLObject(Attribute.class);
- attribute.setFriendlyName(friendlyName);
- attribute.setName(name);
- attribute.getAttributeValues().add(buildAttributeIntegerValue(value));
- return attribute;
- }
-
- public static Attribute buildPVPVersion(String value) {
- return buildStringAttribute("PVP-VERSION",
- "urn:oid:1.2.40.0.10.2.1.1.261.10", value);
- }
-
- public static Attribute buildSecClass(int value) {
- return buildIntegerAttribute("SECCLASS",
- "", value);
- }
-
- public static Attribute buildPrincipalName(String value) {
- return buildStringAttribute("PRINCIPAL-NAME",
- "urn:oid:1.2.40.0.10.2.1.1.261.20", value);
- }
-
- public static Attribute buildGivenName(String value) {
- return buildStringAttribute("GIVEN-NAME",
- "urn:oid:2.5.4.42", value);
- }
-
- public static Attribute buildBirthday(String value) {
- return buildStringAttribute("BIRTHDATE",
- "urn:oid:1.2.40.0.10.2.1.1.55", value);
- }
-
- public static Attribute buildBPK(String value) {
- return buildStringAttribute("BPK",
- "urn:oid:1.2.40.0.10.2.1.1.149", value);
- }
-
- public static Attribute buildEID_CITIZEN_QAALEVEL(int value) {
- return buildIntegerAttribute("EID-CITIZEN-QAA-LEVEL",
- "urn:oid:1.2.40.0.10.2.1.1.261.94", value);
- }
-
- public static Attribute buildEID_ISSUING_NATION(String value) {
- return buildStringAttribute("EID-ISSUING-NATION",
- "urn:oid:1.2.40.0.10.2.1.1.261.32", value);
- }
-
- public static Attribute buildEID_SECTOR_FOR_IDENTIFIER(String value) {
- return buildStringAttribute("EID-SECTOR-FOR-IDENTIFIER",
- "urn:oid:1.2.40.0.10.2.1.1.261.34", value);
- }
-
+ /**
+ * Build simple attribute.
+ *
+ * @param value Attributevalue
+ * @return XML attribute
+ */
+ public static XMLObject buildAttributeStringValue(final String value) {
+ final XSStringBuilder stringBuilder =
+ (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
+ final XSString stringValue =
+ stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
+ stringValue.setValue(value);
+ return stringValue;
+ }
+
+ /**
+ * Build simple attribute.
+ *
+ * @param value Attributevalue
+ * @return XML attribute
+ */
+ public static XMLObject buildAttributeIntegerValue(final int value) {
+ final XSIntegerBuilder integerBuilder =
+ (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(
+ XSInteger.TYPE_NAME);
+ final XSInteger integerValue =
+ integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
+ integerValue.setValue(value);
+ return integerValue;
+ }
+
+ /**
+ * Build simple attribute.
+ *
+ * @param friendlyName attribute friendly-name
+ * @param value Attributevalue
+ * @return XML attribute
+ */
+ public static Attribute buildStringAttribute(final String friendlyName, final String name,
+ final String value) {
+ final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setName(name);
+ attribute.getAttributeValues().add(buildAttributeStringValue(value));
+ return attribute;
+ }
+
+ /**
+ * Build simple attribute.
+ *
+ * @param friendlyName attribute friendly-name
+ * @param value Attributevalue
+ * @return XML attribute
+ */
+ public static Attribute buildIntegerAttribute(final String friendlyName, final String name,
+ final int value) {
+ final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setName(name);
+ attribute.getAttributeValues().add(buildAttributeIntegerValue(value));
+ return attribute;
+ }
+
+ /**
+ * Build PVP version attribute.
+ *
+ * @param value PVP Version
+ * @return SAML2 Attribute
+ */
+ public static Attribute buildPvpVersion(final String value) {
+ return buildStringAttribute("PVP-VERSION", "urn:oid:1.2.40.0.10.2.1.1.261.10", value);
+ }
+
+ public static Attribute buildSecClass(final int value) {
+ return buildIntegerAttribute("SECCLASS", "", value);
+ }
+
+ public static Attribute buildPrincipalName(final String value) {
+ return buildStringAttribute("PRINCIPAL-NAME", "urn:oid:1.2.40.0.10.2.1.1.261.20", value);
+ }
+
+ public static Attribute buildGivenName(final String value) {
+ return buildStringAttribute("GIVEN-NAME", "urn:oid:2.5.4.42", value);
+ }
+
+ public static Attribute buildBirthday(final String value) {
+ return buildStringAttribute("BIRTHDATE", "urn:oid:1.2.40.0.10.2.1.1.55", value);
+ }
+
+ public static Attribute buildBpk(final String value) {
+ return buildStringAttribute("BPK", "urn:oid:1.2.40.0.10.2.1.1.149", value);
+ }
+
+ public static Attribute buildEid_Citizen_QaaLevel(final int value) {
+ return buildIntegerAttribute("EID-CITIZEN-QAA-LEVEL", "urn:oid:1.2.40.0.10.2.1.1.261.94",
+ value);
+ }
+
+ public static Attribute buildEid_Issuing_Nation(final String value) {
+ return buildStringAttribute("EID-ISSUING-NATION", "urn:oid:1.2.40.0.10.2.1.1.261.32", value);
+ }
+
+ public static Attribute buildEid_Sector_For_Identifier(final String value) {
+ return buildStringAttribute("EID-SECTOR-FOR-IDENTIFIER", "urn:oid:1.2.40.0.10.2.1.1.261.34",
+ value);
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java
deleted file mode 100644
index 0d9e38e0..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ServiceLoader;
-
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.metadata.RequestedAttribute;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder;
-import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;
-import at.gv.egiz.eaaf.core.api.idp.IAuthData;
-import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
-import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException;
-import at.gv.egiz.eaaf.core.exceptions.InvalidDateFormatAttributeException;
-import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException;
-import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PVPMETADATA;
-import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidDateFormatException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
-
-public class PVPAttributeBuilder {
-
- private static final Logger log = LoggerFactory.getLogger(PVPAttributeBuilder.class);
-
- private static IAttributeGenerator<Attribute> generator = new SamlAttributeGenerator();
- private static HashMap<String, IAttributeBuilder> builders;
-
- private static ServiceLoader<IAttributeBuilder> attributBuilderLoader =
- ServiceLoader.load(IAttributeBuilder.class);
-
- private static void addBuilder(IAttributeBuilder builder) {
- builders.put(builder.getName(), builder);
- }
-
- static {
- builders = new HashMap<String, IAttributeBuilder>();
-
- log.info("Loading protocol attribut-builder modules:");
- if (attributBuilderLoader != null ) {
- Iterator<IAttributeBuilder> moduleLoaderInterator = attributBuilderLoader.iterator();
- while (moduleLoaderInterator.hasNext()) {
- try {
- IAttributeBuilder modul = moduleLoaderInterator.next();
- log.info("Loading attribut-builder Modul Information: " + modul.getName());
- addBuilder(modul);
-
- } catch(Throwable e) {
- log.error("Check configuration! " + "Some attribute-builder modul" +
- " is not a valid IAttributeBuilder", e);
- }
- }
- }
-
- log.info("Loading attribute-builder modules done");
-
- }
-
-
- /**
- * Get a specific attribute builder
- *
- * @param name Attribute-builder friendly name
- *
- * @return Attribute-builder with this name or null if builder does not exists
- */
- public static IAttributeBuilder getAttributeBuilder(String name) {
- return builders.get(name);
-
- }
-
- public static Attribute buildAttribute(String name, ISPConfiguration oaParam,
- IAuthData authData) throws PVP2Exception, AttributeBuilderException {
- if (builders.containsKey(name)) {
- try {
- return builders.get(name).build(oaParam, authData, generator);
- }
- catch (AttributeBuilderException e) {
- if (e instanceof UnavailableAttributeException) {
- throw e;
-
- } else if (e instanceof InvalidDateFormatAttributeException) {
- throw new InvalidDateFormatException();
-
- } else {
- throw new UnavailableAttributeException(name);
-
- }
- }
- }
- return null;
- }
-
- public static Attribute buildEmptyAttribute(String name) {
- if (builders.containsKey(name)) {
- return builders.get(name).buildEmpty(generator);
- }
- return null;
- }
-
- public static Attribute buildAttribute(String name, String value) {
- if (builders.containsKey(name)) {
- return builders.get(name).buildEmpty(generator);
- }
- return null;
- }
-
-
- /**
- * Return all attributes that has a {@link PVPMETADATA} annotation
- *
- * @return
- */
- public static List<Attribute> buildSupportedEmptyAttributes() {
- List<Attribute> attributes = new ArrayList<Attribute>();
- Iterator<IAttributeBuilder> builderIt = builders.values().iterator();
- while (builderIt.hasNext()) {
- IAttributeBuilder builder = builderIt.next();
- if (builder.getClass().isAnnotationPresent(PVPMETADATA.class)) {
- Attribute emptyAttribute = builder.buildEmpty(generator);
- if (emptyAttribute != null) {
- attributes.add(emptyAttribute);
- }
-
- } else {
- log.trace(builder.getName() + "is no PVP Metadata attribute");
-
- }
- }
- return attributes;
- }
-
- public static RequestedAttribute buildReqAttribute(String name, String friendlyName, boolean required) {
- RequestedAttribute attribute = SAML2Utils.createSAMLObject(RequestedAttribute.class);
- attribute.setIsRequired(required);
- attribute.setName(name);
- attribute.setFriendlyName(friendlyName);
- attribute.setNameFormat(Attribute.URI_REFERENCE);
- return attribute;
- }
-
- /**
- * Build a set of PVP Response-Attributes
- * <br><br>
- * <b>INFO:</b> If a specific attribute can not be build, a info is logged, but no execpetion is thrown.
- * Therefore, the return List must not include all requested attributes.
- *
- * @param authData AuthenticationData <code>IAuthData</code> which is used to build the attribute values, but never <code>null</code>
- * @param reqAttributenName List of PVP attribute names which are requested, but never <code>null</code>
- * @return List of PVP attributes, but never <code>null</code>
- */
- public static List<Attribute> buildSetOfResponseAttributes(IAuthData authData,
- Collection<String> reqAttributenName) {
- List<Attribute> attrList = new ArrayList<Attribute>();
- if (reqAttributenName != null) {
- Iterator<String> it = reqAttributenName.iterator();
- while (it.hasNext()) {
- String reqAttributName = it.next();
- try {
- Attribute attr = PVPAttributeBuilder.buildAttribute(
- reqAttributName, null, authData);
- if (attr == null) {
- log.info(
- "Attribute generation failed! for "
- + reqAttributName);
-
- } else {
- attrList.add(attr);
-
- }
-
- } catch (PVP2Exception e) {
- log.info(
- "Attribute generation failed! for "
- + reqAttributName);
-
- } catch (Exception e) {
- log.warn(
- "General Attribute generation failed! for "
- + reqAttributName, e);
-
- }
- }
- }
-
- return attrList;
- }
-
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java
deleted file mode 100644
index 61c6006b..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.List;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.opensaml.Configuration;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.AttributeConsumingService;
-import org.opensaml.saml2.metadata.ContactPerson;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.KeyDescriptor;
-import org.opensaml.saml2.metadata.LocalizedString;
-import org.opensaml.saml2.metadata.NameIDFormat;
-import org.opensaml.saml2.metadata.Organization;
-import org.opensaml.saml2.metadata.RequestedAttribute;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.ServiceName;
-import org.opensaml.saml2.metadata.SingleLogoutService;
-import org.opensaml.saml2.metadata.SingleSignOnService;
-import org.opensaml.xml.io.Marshaller;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.security.SecurityException;
-import org.opensaml.xml.security.SecurityHelper;
-import org.opensaml.xml.security.credential.Credential;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.keyinfo.KeyInfoGenerator;
-import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory;
-import org.opensaml.xml.signature.Signature;
-import org.opensaml.xml.signature.SignatureException;
-import org.opensaml.xml.signature.Signer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-import org.w3c.dom.Document;
-
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
-
-/**
- * @author tlenz
- *
- */
-
-@Service("PVPMetadataBuilder")
-public class PVPMetadataBuilder {
-
- private static final Logger log = LoggerFactory.getLogger(PVPMetadataBuilder.class);
-
- X509KeyInfoGeneratorFactory keyInfoFactory = null;
-
- /**
- *
- */
- public PVPMetadataBuilder() {
- keyInfoFactory = new X509KeyInfoGeneratorFactory();
- keyInfoFactory.setEmitEntityIDAsKeyName(true);
- keyInfoFactory.setEmitEntityCertificate(true);
-
- }
-
-
- /**
- *
- * Build PVP 2.1 conform SAML2 metadata
- *
- * @param config
- * PVPMetadataBuilder configuration
- *
- * @return PVP metadata as XML String
- * @throws SecurityException
- * @throws ConfigurationException
- * @throws CredentialsNotAvailableException
- * @throws TransformerFactoryConfigurationError
- * @throws MarshallingException
- * @throws TransformerException
- * @throws ParserConfigurationException
- * @throws IOException
- * @throws SignatureException
- */
- public String buildPVPMetadata(IPVPMetadataBuilderConfiguration config) throws CredentialsNotAvailableException, EAAFException, SecurityException, TransformerFactoryConfigurationError, MarshallingException, TransformerException, ParserConfigurationException, IOException, SignatureException {
- DateTime date = new DateTime();
- EntityDescriptor entityDescriptor = SAML2Utils
- .createSAMLObject(EntityDescriptor.class);
-
- //set entityID
- entityDescriptor.setEntityID(config.getEntityID());
-
- //set contact and organisation information
- List<ContactPerson> contactPersons = config.getContactPersonInformation();
- if (contactPersons != null)
- entityDescriptor.getContactPersons().addAll(contactPersons);
-
- Organization organisation = config.getOrgansiationInformation();
- if (organisation != null)
- entityDescriptor.setOrganization(organisation);
-
- //set IDP metadata
- if (config.buildIDPSSODescriptor()) {
- RoleDescriptor idpSSODesc = generateIDPMetadata(config);
- if (idpSSODesc != null)
- entityDescriptor.getRoleDescriptors().add(idpSSODesc);
-
- }
-
- //set SP metadata for interfederation
- if (config.buildSPSSODescriptor()) {
- RoleDescriptor spSSODesc = generateSPMetadata(config);
- if (spSSODesc != null)
- entityDescriptor.getRoleDescriptors().add(spSSODesc);
-
- }
-
- //set metadata signature parameters
- Credential metadataSignCred = config.getMetadataSigningCredentials();
- Signature signature = AbstractCredentialProvider.getIDPSignature(metadataSignCred);
- SecurityHelper.prepareSignatureParams(signature, metadataSignCred, null, null);
-
- //initialize XML document builder
- DocumentBuilder builder;
- DocumentBuilderFactory factory = DocumentBuilderFactory
- .newInstance();
-
- builder = factory.newDocumentBuilder();
- Document document = builder.newDocument();
-
-
- //build entities descriptor
- if (config.buildEntitiesDescriptorAsRootElement()) {
- EntitiesDescriptor entitiesDescriptor =
- SAML2Utils.createSAMLObject(EntitiesDescriptor.class);
- entitiesDescriptor.setName(config.getEntityFriendlyName());
- entitiesDescriptor.setID(SAML2Utils.getSecureIdentifier());
- entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));
- entitiesDescriptor.getEntityDescriptors().add(entityDescriptor);
-
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
- entitiesDescriptor.setSignature(signature);
-
-
- //marshall document
- Marshaller out = Configuration.getMarshallerFactory()
- .getMarshaller(entitiesDescriptor);
- out.marshall(entitiesDescriptor, document);
-
- } else {
- entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));
- entityDescriptor.setID(SAML2Utils.getSecureIdentifier());
-
- entityDescriptor.setSignature(signature);
-
-
-
- //marshall document
- Marshaller out = Configuration.getMarshallerFactory()
- .getMarshaller(entityDescriptor);
- out.marshall(entityDescriptor, document);
-
- }
-
- //sign metadata
- Signer.signObject(signature);
-
- //transform metadata object to XML string
- Transformer transformer = TransformerFactory.newInstance()
- .newTransformer();
-
- StringWriter sw = new StringWriter();
- StreamResult sr = new StreamResult(sw);
- DOMSource source = new DOMSource(document);
- transformer.transform(source, sr);
- sw.close();
-
- return sw.toString();
- }
-
-
- private RoleDescriptor generateSPMetadata(IPVPMetadataBuilderConfiguration config) throws CredentialsNotAvailableException, SecurityException, EAAFException {
- SPSSODescriptor spSSODescriptor = SAML2Utils.createSAMLObject(SPSSODescriptor.class);
- spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
- spSSODescriptor.setAuthnRequestsSigned(config.wantAuthnRequestSigned());
- spSSODescriptor.setWantAssertionsSigned(config.wantAssertionSigned());
-
- KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance();
-
- //Set AuthRequest Signing certificate
- Credential authcredential = config.getRequestorResponseSigningCredentials();
- if (authcredential == null) {
- log.warn("SP Metadata generation FAILED! --> Builder has NO request signing-credential. ");
- return null;
-
- } else {
- KeyDescriptor signKeyDescriptor = SAML2Utils
- .createSAMLObject(KeyDescriptor.class);
- signKeyDescriptor.setUse(UsageType.SIGNING);
- signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential));
- spSSODescriptor.getKeyDescriptors().add(signKeyDescriptor);
-
- }
-
- //Set assertion encryption credentials
- Credential authEncCredential = config.getEncryptionCredentials();
-
- if (authEncCredential != null) {
- KeyDescriptor encryKeyDescriptor = SAML2Utils
- .createSAMLObject(KeyDescriptor.class);
- encryKeyDescriptor.setUse(UsageType.ENCRYPTION);
- encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential));
- spSSODescriptor.getKeyDescriptors().add(encryKeyDescriptor);
-
- } else {
- log.warn("No Assertion Encryption-Key defined. This setting is not recommended!");
-
- }
-
- //check nameID formates
- if (config.getSPAllowedNameITTypes() == null || config.getSPAllowedNameITTypes().size() == 0) {
- log.warn("SP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. ");
- return null;
-
- } else {
- for (String format : config.getSPAllowedNameITTypes()) {
- NameIDFormat nameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class);
- nameIDFormat.setFormat(format);
- spSSODescriptor.getNameIDFormats().add(nameIDFormat);
-
- }
- }
-
-
- //add POST-Binding assertion consumer services
- if (StringUtils.isNotEmpty(config.getSPAssertionConsumerServicePostBindingURL())) {
- AssertionConsumerService postassertionConsumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class);
- postassertionConsumerService.setIndex(0);
- postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
- postassertionConsumerService.setLocation(config.getSPAssertionConsumerServicePostBindingURL());
- postassertionConsumerService.setIsDefault(true);
- spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService);
-
- }
-
- //add POST-Binding assertion consumer services
- if (StringUtils.isNotEmpty(config.getSPAssertionConsumerServiceRedirectBindingURL())) {
- AssertionConsumerService redirectassertionConsumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class);
- redirectassertionConsumerService.setIndex(1);
- redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- redirectassertionConsumerService.setLocation(config.getSPAssertionConsumerServiceRedirectBindingURL());
- spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService);
-
- }
-
- //validate WebSSO endpoints
- if (spSSODescriptor.getAssertionConsumerServices().size() == 0) {
- log.warn("SP Metadata generation FAILED! --> NO SAML2 AssertionConsumerService endpoint found. ");
- return null;
-
- }
-
- //add POST-Binding SLO descriptor
- if (StringUtils.isNotEmpty(config.getSPSLOPostBindingURL())) {
- SingleLogoutService postSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
- postSLOService.setLocation(config.getSPSLOPostBindingURL());
- postSLOService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
- spSSODescriptor.getSingleLogoutServices().add(postSLOService);
-
- }
-
- //add POST-Binding SLO descriptor
- if (StringUtils.isNotEmpty(config.getSPSLORedirectBindingURL())) {
- SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
- redirectSLOService.setLocation(config.getSPSLORedirectBindingURL());
- redirectSLOService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- spSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
-
- }
-
- //add POST-Binding SLO descriptor
- if (StringUtils.isNotEmpty(config.getSPSLOSOAPBindingURL())) {
- SingleLogoutService soapSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
- soapSLOService.setLocation(config.getSPSLOSOAPBindingURL());
- soapSLOService.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI);
- spSSODescriptor.getSingleLogoutServices().add(soapSLOService);
-
- }
-
-
- //add required attributes
- Collection<RequestedAttribute> reqSPAttr = config.getSPRequiredAttributes();
- AttributeConsumingService attributeService = SAML2Utils.createSAMLObject(AttributeConsumingService.class);
-
- attributeService.setIndex(0);
- attributeService.setIsDefault(true);
- ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class);
- serviceName.setName(new LocalizedString("Default Service", "en"));
- attributeService.getNames().add(serviceName);
-
- if (reqSPAttr != null && reqSPAttr.size() > 0) {
- log.debug("Add " + reqSPAttr.size() + " attributes to SP metadata");
- attributeService.getRequestAttributes().addAll(reqSPAttr);
-
- } else {
- log.debug("SP metadata contains NO requested attributes.");
-
- }
-
- spSSODescriptor.getAttributeConsumingServices().add(attributeService);
-
- return spSSODescriptor;
- }
-
- private IDPSSODescriptor generateIDPMetadata(IPVPMetadataBuilderConfiguration config) throws EAAFException, CredentialsNotAvailableException, SecurityException {
- //check response signing credential
- Credential responseSignCred = config.getRequestorResponseSigningCredentials();
- if (responseSignCred == null) {
- log.warn("IDP Metadata generation FAILED! --> Builder has NO Response signing credential. ");
- return null;
-
- }
-
- //check nameID formates
- if (config.getIDPPossibleNameITTypes() == null || config.getIDPPossibleNameITTypes().size() == 0) {
- log.warn("IDP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. ");
- return null;
-
- }
-
- // build SAML2 IDP-SSO descriptor element
- IDPSSODescriptor idpSSODescriptor = SAML2Utils
- .createSAMLObject(IDPSSODescriptor.class);
-
- idpSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
-
- //set ass default value, because PVP 2.x specification defines this feature as MUST
- idpSSODescriptor.setWantAuthnRequestsSigned(config.wantAuthnRequestSigned());
-
- // add WebSSO descriptor for POST-Binding
- if (StringUtils.isNotEmpty(config.getIDPWebSSOPostBindingURL())) {
- SingleSignOnService postSingleSignOnService = SAML2Utils.createSAMLObject(SingleSignOnService.class);
- postSingleSignOnService.setLocation(config.getIDPWebSSOPostBindingURL());
- postSingleSignOnService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
- idpSSODescriptor.getSingleSignOnServices().add(postSingleSignOnService);
-
- }
-
- // add WebSSO descriptor for Redirect-Binding
- if (StringUtils.isNotEmpty(config.getIDPWebSSORedirectBindingURL())) {
- SingleSignOnService postSingleSignOnService = SAML2Utils.createSAMLObject(SingleSignOnService.class);
- postSingleSignOnService.setLocation(config.getIDPWebSSORedirectBindingURL());
- postSingleSignOnService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- idpSSODescriptor.getSingleSignOnServices().add(postSingleSignOnService);
-
- }
-
- //add Single LogOut POST-Binding endpoing
- if (StringUtils.isNotEmpty(config.getIDPSLOPostBindingURL())) {
- SingleLogoutService postSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
- postSLOService.setLocation(config.getIDPSLOPostBindingURL());
- postSLOService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
- idpSSODescriptor.getSingleLogoutServices().add(postSLOService);
-
- }
-
- //add Single LogOut Redirect-Binding endpoing
- if (StringUtils.isNotEmpty(config.getIDPSLORedirectBindingURL())) {
- SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
- redirectSLOService.setLocation(config.getIDPSLORedirectBindingURL());
- redirectSLOService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
- idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService);
-
- }
-
- //validate WebSSO endpoints
- if (idpSSODescriptor.getSingleSignOnServices().size() == 0) {
- log.warn("IDP Metadata generation FAILED! --> NO SAML2 SingleSignOnService endpoint found. ");
- return null;
-
- }
-
- //set assertion signing key
- KeyDescriptor signKeyDescriptor = SAML2Utils
- .createSAMLObject(KeyDescriptor.class);
- signKeyDescriptor.setUse(UsageType.SIGNING);
- KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance();
- signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(config.getRequestorResponseSigningCredentials()));
- idpSSODescriptor.getKeyDescriptors().add(signKeyDescriptor);
-
- //set IDP attribute set
- idpSSODescriptor.getAttributes().addAll(config.getIDPPossibleAttributes());
-
- //set providable nameID formats
- for (String format : config.getIDPPossibleNameITTypes()) {
- NameIDFormat nameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class);
- nameIDFormat.setFormat(format);
- idpSSODescriptor.getNameIDFormats().add(nameIDFormat);
-
- }
-
- return idpSSODescriptor;
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java
new file mode 100644
index 00000000..92e75e17
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder;
+import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.InvalidDateFormatAttributeException;
+import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException;
+import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PvpMetadata;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidDateFormatException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PvpAttributeBuilder {
+
+ private static final Logger log = LoggerFactory.getLogger(PvpAttributeBuilder.class);
+
+ private static IAttributeGenerator<Attribute> generator = new SamlAttributeGenerator();
+ private static HashMap<String, IAttributeBuilder> builders;
+
+ private static ServiceLoader<IAttributeBuilder> attributBuilderLoader =
+ ServiceLoader.load(IAttributeBuilder.class);
+
+ private static void addBuilder(final IAttributeBuilder builder) {
+ builders.put(builder.getName(), builder);
+ }
+
+ static {
+ builders = new HashMap<>();
+
+ log.info("Loading protocol attribut-builder modules:");
+ if (attributBuilderLoader != null) {
+ final Iterator<IAttributeBuilder> moduleLoaderInterator = attributBuilderLoader.iterator();
+ while (moduleLoaderInterator.hasNext()) {
+ try {
+ final IAttributeBuilder modul = moduleLoaderInterator.next();
+ log.info("Loading attribut-builder Modul Information: " + modul.getName());
+ addBuilder(modul);
+
+ } catch (final Throwable e) {
+ log.error("Check configuration! " + "Some attribute-builder modul"
+ + " is not a valid IAttributeBuilder", e);
+ }
+ }
+ }
+
+ log.info("Loading attribute-builder modules done");
+
+ }
+
+ /**
+ * Get a specific attribute builder.
+ *
+ * @param name Attribute-builder friendly name
+ *
+ * @return Attribute-builder with this name or null if builder does not exists
+ */
+ public static IAttributeBuilder getAttributeBuilder(final String name) {
+ return builders.get(name);
+
+ }
+
+ /**
+ * Build an SAML2 attribute.
+ *
+ * @param name attribute name
+ * @param value attribute value
+ * @return SAML2 attribute
+ */
+ public static Attribute buildAttribute(final String name, final String value) {
+ log.warn("Attribute value: {} is NOT injected", value);
+
+ if (builders.containsKey(name)) {
+ return builders.get(name).buildEmpty(generator);
+ }
+ return null;
+ }
+
+ /**
+ * Build a SAML2 attribute.
+ *
+ * @param name attribute name
+ * @param oaParam Service-Provider configuration
+ * @param authData serice-provider specific authentication data
+ * @return SAML2 attribute
+ * @throws Pvp2Exception In case of a general error
+ * @throws AttributeBuilderException In case of an attribute builder error
+ */
+ public static Attribute buildAttribute(final String name, final ISpConfiguration oaParam,
+ final IAuthData authData) throws Pvp2Exception, AttributeBuilderException {
+ if (builders.containsKey(name)) {
+ try {
+ return builders.get(name).build(oaParam, authData, generator);
+ } catch (final AttributeBuilderException e) {
+ if (e instanceof UnavailableAttributeException) {
+ throw e;
+
+ } else if (e instanceof InvalidDateFormatAttributeException) {
+ throw new InvalidDateFormatException();
+
+ } else {
+ throw new UnavailableAttributeException(name);
+
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Build an empty attribute.
+ *
+ * @param name attributename
+ * @return SAML2 attribute
+ */
+ public static Attribute buildEmptyAttribute(final String name) {
+ if (builders.containsKey(name)) {
+ return builders.get(name).buildEmpty(generator);
+ }
+ return null;
+ }
+
+ /**
+ * Return all attributes that has a {@link PvpMetadata} annotation.
+ *
+ * @return
+ */
+ public static List<Attribute> buildSupportedEmptyAttributes() {
+ final List<Attribute> attributes = new ArrayList<>();
+ final Iterator<IAttributeBuilder> builderIt = builders.values().iterator();
+ while (builderIt.hasNext()) {
+ final IAttributeBuilder builder = builderIt.next();
+ if (builder.getClass().isAnnotationPresent(PvpMetadata.class)) {
+ final Attribute emptyAttribute = builder.buildEmpty(generator);
+ if (emptyAttribute != null) {
+ attributes.add(emptyAttribute);
+ }
+
+ } else {
+ log.trace(builder.getName() + "is no PVP Metadata attribute");
+
+ }
+ }
+ return attributes;
+ }
+
+ /**
+ * Build a requested attribute.
+ *
+ * @param name attribute name
+ * @param friendlyName attribute friendlyname
+ * @param required is attribute mandatory
+ * @return SAML2 requested attribute
+ */
+ public static RequestedAttribute buildReqAttribute(final String name, final String friendlyName,
+ final boolean required) {
+ final RequestedAttribute attribute = Saml2Utils.createSamlObject(RequestedAttribute.class);
+ attribute.setIsRequired(required);
+ attribute.setName(name);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setNameFormat(Attribute.URI_REFERENCE);
+ return attribute;
+ }
+
+ /**
+ * Build a set of PVP Response-Attributes <br>
+ * <br>
+ * <b>INFO:</b> If a specific attribute can not be build, a info is logged, but
+ * no execpetion is thrown. Therefore, the return List must not include all
+ * requested attributes.
+ *
+ * @param authData AuthenticationData <code>IAuthData</code> which is
+ * used to build the attribute values, but never
+ * <code>null</code>
+ * @param reqAttributenName List of PVP attribute names which are requested, but
+ * never <code>null</code>
+ * @return List of PVP attributes, but never <code>null</code>
+ */
+ public static List<Attribute> buildSetOfResponseAttributes(final IAuthData authData,
+ final Collection<String> reqAttributenName) {
+ final List<Attribute> attrList = new ArrayList<>();
+ if (reqAttributenName != null) {
+ final Iterator<String> it = reqAttributenName.iterator();
+ while (it.hasNext()) {
+ final String reqAttributName = it.next();
+ try {
+ final Attribute attr =
+ PvpAttributeBuilder.buildAttribute(reqAttributName, null, authData);
+ if (attr == null) {
+ log.info("Attribute generation failed! for " + reqAttributName);
+
+ } else {
+ attrList.add(attr);
+
+ }
+
+ } catch (final Pvp2Exception e) {
+ log.info("Attribute generation failed! for " + reqAttributName);
+
+ } catch (final Exception e) {
+ log.warn("General Attribute generation failed! for " + reqAttributName, e);
+
+ }
+ }
+ }
+
+ return attrList;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
new file mode 100644
index 00000000..92922e09
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.List;
+
+import javax.naming.ConfigurationException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
+import org.opensaml.saml.saml2.metadata.ContactPerson;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.KeyDescriptor;
+import org.opensaml.saml.saml2.metadata.NameIDFormat;
+import org.opensaml.saml.saml2.metadata.Organization;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.saml.saml2.metadata.RoleDescriptor;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.ServiceName;
+import org.opensaml.saml.saml2.metadata.SingleLogoutService;
+import org.opensaml.saml.saml2.metadata.SingleSignOnService;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
+import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+
+/**
+ * PVP metadata builder implementation.
+ *
+ * @author tlenz
+ *
+ */
+
+public class PvpMetadataBuilder {
+
+ private static final String ERROR_ROLE_DESCR = "Can not build {0}";
+
+ private static final Logger log = LoggerFactory.getLogger(PvpMetadataBuilder.class);
+
+ X509KeyInfoGeneratorFactory keyInfoFactory = null;
+
+ /**
+ * PVP metadata builder.
+ *
+ */
+ public PvpMetadataBuilder() {
+ keyInfoFactory = new X509KeyInfoGeneratorFactory();
+ keyInfoFactory.setEmitEntityIDAsKeyName(true);
+ keyInfoFactory.setEmitEntityCertificate(true);
+
+ }
+
+ /**
+ * Build PVP 2.1 conform SAML2 metadata.
+ *
+ * @param config PVPMetadataBuilder configuration*
+ * @return PVP metadata as XML String
+ * @throws SecurityException In case of an error
+ * @throws ConfigurationException In case of an error
+ * @throws CredentialsNotAvailableException In case of an error
+ * @throws TransformerFactoryConfigurationError In case of an error
+ * @throws MarshallingException In case of an error
+ * @throws TransformerException In case of an error
+ * @throws ParserConfigurationException In case of an error
+ * @throws IOException In case of an error
+ * @throws SignatureException In case of an error
+ */
+ public String buildPvpMetadata(final IPvpMetadataBuilderConfiguration config)
+ throws CredentialsNotAvailableException, EaafException, SecurityException,
+ TransformerFactoryConfigurationError, MarshallingException, TransformerException,
+ ParserConfigurationException, IOException, SignatureException {
+ final DateTime date = new DateTime();
+ final EntityDescriptor entityDescriptor = Saml2Utils.createSamlObject(EntityDescriptor.class);
+
+ // set entityID
+ entityDescriptor.setEntityID(config.getEntityID());
+
+ // set contact and organisation information
+ final List<ContactPerson> contactPersons = config.getContactPersonInformation();
+ if (contactPersons != null) {
+ entityDescriptor.getContactPersons().addAll(contactPersons);
+ }
+
+ final Organization organisation = config.getOrgansiationInformation();
+ if (organisation != null) {
+ entityDescriptor.setOrganization(organisation);
+ }
+
+ // set IDP metadata
+ if (config.buildIdpSsoDescriptor()) {
+ final RoleDescriptor idpSsoDesc = generateIdpMetadata(config);
+ if (idpSsoDesc != null) {
+ entityDescriptor.getRoleDescriptors().add(idpSsoDesc);
+
+ } else {
+ final String msg = MessageFormat.format(ERROR_ROLE_DESCR,
+ IDPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME);
+ throw new EaafBuilderException("internal.pvp.13", new Object[] { msg }, msg);
+
+ }
+
+ }
+
+ // set SP metadata for interfederation
+ if (config.buildSpSsoDescriptor()) {
+ final RoleDescriptor spSsoDesc = generateSpMetadata(config);
+ if (spSsoDesc != null) {
+ entityDescriptor.getRoleDescriptors().add(spSsoDesc);
+
+ } else {
+ final String msg = MessageFormat.format(ERROR_ROLE_DESCR, SPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME);
+ throw new EaafBuilderException("internal.pvp.13", new Object[] { msg }, msg);
+
+ }
+
+ }
+
+ SignableSAMLObject metadataToSign;
+
+ // build entities descriptor
+ if (config.buildEntitiesDescriptorAsRootElement()) {
+ final EntitiesDescriptor entitiesDescriptor =
+ Saml2Utils.createSamlObject(EntitiesDescriptor.class);
+ entitiesDescriptor.setName(config.getEntityFriendlyName());
+ entitiesDescriptor.setID(Saml2Utils.getSecureIdentifier());
+ entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));
+ entitiesDescriptor.getEntityDescriptors().add(entityDescriptor);
+ metadataToSign = entitiesDescriptor;
+
+ } else {
+ entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil()));
+ entityDescriptor.setID(Saml2Utils.getSecureIdentifier());
+ metadataToSign = entityDescriptor;
+
+ }
+
+ // sign metadata
+ final EaafX509Credential metadataSignCred = config.getMetadataSigningCredentials();
+ final SignableSAMLObject signedMetadata = Saml2Utils.signSamlObject(metadataToSign, metadataSignCred,
+ true);
+
+ // Serialize metadata
+ final Element document = XMLObjectSupport.marshall(signedMetadata);
+ final String serializedMetadata = SerializeSupport.nodeToString(document);
+ return serializedMetadata;
+
+ }
+
+ private RoleDescriptor generateSpMetadata(final IPvpMetadataBuilderConfiguration config)
+ throws SecurityException, EaafException {
+ final SPSSODescriptor spSsoDescriptor = Saml2Utils.createSamlObject(SPSSODescriptor.class);
+ spSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
+ spSsoDescriptor.setAuthnRequestsSigned(config.wantAuthnRequestSigned());
+ spSsoDescriptor.setWantAssertionsSigned(config.wantAssertionSigned());
+
+ final KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance();
+
+ // Set AuthRequest Signing certificate
+ final Credential authcredential = config.getRequestorResponseSigningCredentials();
+ if (authcredential == null) {
+ log.warn("SP Metadata generation FAILED! --> Builder has NO request signing-credential. ");
+ return null;
+
+ } else {
+ final KeyDescriptor signKeyDescriptor = Saml2Utils.createSamlObject(KeyDescriptor.class);
+ signKeyDescriptor.setUse(UsageType.SIGNING);
+ signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential));
+ spSsoDescriptor.getKeyDescriptors().add(signKeyDescriptor);
+
+ }
+
+ // Set assertion encryption credentials
+ final Credential authEncCredential = config.getEncryptionCredentials();
+
+ if (authEncCredential != null) {
+ final KeyDescriptor encryKeyDescriptor = Saml2Utils.createSamlObject(KeyDescriptor.class);
+ encryKeyDescriptor.setUse(UsageType.ENCRYPTION);
+ encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential));
+ spSsoDescriptor.getKeyDescriptors().add(encryKeyDescriptor);
+
+ } else {
+ log.warn("No Assertion Encryption-Key defined. This setting is not recommended!");
+
+ }
+
+ // check nameID formates
+ if (config.getSpAllowedNameIdTypes() == null || config.getSpAllowedNameIdTypes().size() == 0) {
+ log.warn(
+ "SP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. ");
+ return null;
+
+ } else {
+ for (final String format : config.getSpAllowedNameIdTypes()) {
+ final NameIDFormat nameIdFormat = Saml2Utils.createSamlObject(NameIDFormat.class);
+ nameIdFormat.setFormat(format);
+ spSsoDescriptor.getNameIDFormats().add(nameIdFormat);
+
+ }
+ }
+
+ // add POST-Binding assertion consumer services
+ if (StringUtils.isNotEmpty(config.getSpAssertionConsumerServicePostBindingUrl())) {
+ final AssertionConsumerService postassertionConsumerService =
+ Saml2Utils.createSamlObject(AssertionConsumerService.class);
+ postassertionConsumerService.setIndex(0);
+ postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+ postassertionConsumerService
+ .setLocation(config.getSpAssertionConsumerServicePostBindingUrl());
+ postassertionConsumerService.setIsDefault(true);
+ spSsoDescriptor.getAssertionConsumerServices().add(postassertionConsumerService);
+
+ }
+
+ // add POST-Binding assertion consumer services
+ if (StringUtils.isNotEmpty(config.getSpAssertionConsumerServiceRedirectBindingUrl())) {
+ final AssertionConsumerService redirectassertionConsumerService =
+ Saml2Utils.createSamlObject(AssertionConsumerService.class);
+ redirectassertionConsumerService.setIndex(1);
+ redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ redirectassertionConsumerService
+ .setLocation(config.getSpAssertionConsumerServiceRedirectBindingUrl());
+ spSsoDescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService);
+
+ }
+
+ // validate WebSSO endpoints
+ if (spSsoDescriptor.getAssertionConsumerServices().size() == 0) {
+ log.warn(
+ "SP Metadata generation FAILED! --> NO SAML2 AssertionConsumerService endpoint found. ");
+ return null;
+
+ }
+
+ // add POST-Binding SLO descriptor
+ if (StringUtils.isNotEmpty(config.getSpSloPostBindingUrl())) {
+ final SingleLogoutService postSloService =
+ Saml2Utils.createSamlObject(SingleLogoutService.class);
+ postSloService.setLocation(config.getSpSloPostBindingUrl());
+ postSloService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+ spSsoDescriptor.getSingleLogoutServices().add(postSloService);
+
+ }
+
+ // add POST-Binding SLO descriptor
+ if (StringUtils.isNotEmpty(config.getSpSloRedirectBindingUrl())) {
+ final SingleLogoutService redirectSloService =
+ Saml2Utils.createSamlObject(SingleLogoutService.class);
+ redirectSloService.setLocation(config.getSpSloRedirectBindingUrl());
+ redirectSloService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ spSsoDescriptor.getSingleLogoutServices().add(redirectSloService);
+
+ }
+
+ // add POST-Binding SLO descriptor
+ if (StringUtils.isNotEmpty(config.getSpSloSoapBindingUrl())) {
+ final SingleLogoutService soapSloService =
+ Saml2Utils.createSamlObject(SingleLogoutService.class);
+ soapSloService.setLocation(config.getSpSloSoapBindingUrl());
+ soapSloService.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI);
+ spSsoDescriptor.getSingleLogoutServices().add(soapSloService);
+
+ }
+
+ // add required attributes
+ final Collection<RequestedAttribute> reqSpAttr = config.getSpRequiredAttributes();
+ final AttributeConsumingService attributeService =
+ Saml2Utils.createSamlObject(AttributeConsumingService.class);
+
+ attributeService.setIndex(0);
+ attributeService.setIsDefault(true);
+ final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class);
+ serviceName.setValue("Default Service");
+ serviceName.setXMLLang("en");
+ attributeService.getNames().add(serviceName);
+
+ if (reqSpAttr != null && reqSpAttr.size() > 0) {
+ log.debug("Add " + reqSpAttr.size() + " attributes to SP metadata");
+ attributeService.getRequestAttributes().addAll(reqSpAttr);
+
+ } else {
+ log.debug("SP metadata contains NO requested attributes.");
+
+ }
+
+ spSsoDescriptor.getAttributeConsumingServices().add(attributeService);
+
+ return spSsoDescriptor;
+ }
+
+ private IDPSSODescriptor generateIdpMetadata(final IPvpMetadataBuilderConfiguration config)
+ throws EaafException, SecurityException {
+ // check response signing credential
+ final Credential responseSignCred = config.getRequestorResponseSigningCredentials();
+ if (responseSignCred == null) {
+ log.warn("IDP Metadata generation FAILED! --> Builder has NO Response signing credential. ");
+ return null;
+
+ }
+
+ // check nameID formates
+ if (config.getIdpPossibleNameIdTypes() == null
+ || config.getIdpPossibleNameIdTypes().size() == 0) {
+ log.warn(
+ "IDP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. ");
+ return null;
+
+ }
+
+ // build SAML2 IDP-SSO descriptor element
+ final IDPSSODescriptor idpSsoDescriptor = Saml2Utils.createSamlObject(IDPSSODescriptor.class);
+
+ idpSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
+
+ // set ass default value, because PVP 2.x specification defines this feature as
+ // MUST
+ idpSsoDescriptor.setWantAuthnRequestsSigned(config.wantAuthnRequestSigned());
+
+ // add WebSSO descriptor for POST-Binding
+ if (StringUtils.isNotEmpty(config.getIdpWebSsoPostBindingUrl())) {
+ final SingleSignOnService postSingleSignOnService =
+ Saml2Utils.createSamlObject(SingleSignOnService.class);
+ postSingleSignOnService.setLocation(config.getIdpWebSsoPostBindingUrl());
+ postSingleSignOnService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+ idpSsoDescriptor.getSingleSignOnServices().add(postSingleSignOnService);
+
+ }
+
+ // add WebSSO descriptor for Redirect-Binding
+ if (StringUtils.isNotEmpty(config.getIdpWebSsoRedirectBindingUrl())) {
+ final SingleSignOnService postSingleSignOnService =
+ Saml2Utils.createSamlObject(SingleSignOnService.class);
+ postSingleSignOnService.setLocation(config.getIdpWebSsoRedirectBindingUrl());
+ postSingleSignOnService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ idpSsoDescriptor.getSingleSignOnServices().add(postSingleSignOnService);
+
+ }
+
+ // add Single LogOut POST-Binding endpoing
+ if (StringUtils.isNotEmpty(config.getIdpSloPostBindingUrl())) {
+ final SingleLogoutService postSloService =
+ Saml2Utils.createSamlObject(SingleLogoutService.class);
+ postSloService.setLocation(config.getIdpSloPostBindingUrl());
+ postSloService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+ idpSsoDescriptor.getSingleLogoutServices().add(postSloService);
+
+ }
+
+ // add Single LogOut Redirect-Binding endpoing
+ if (StringUtils.isNotEmpty(config.getIdpSloRedirectBindingUrl())) {
+ final SingleLogoutService redirectSloService =
+ Saml2Utils.createSamlObject(SingleLogoutService.class);
+ redirectSloService.setLocation(config.getIdpSloRedirectBindingUrl());
+ redirectSloService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ idpSsoDescriptor.getSingleLogoutServices().add(redirectSloService);
+
+ }
+
+ // validate WebSSO endpoints
+ if (idpSsoDescriptor.getSingleSignOnServices().size() == 0) {
+ log.warn("IDP Metadata generation FAILED! --> NO SAML2 SingleSignOnService endpoint found. ");
+ return null;
+
+ }
+
+ // set assertion signing key
+ final KeyDescriptor signKeyDescriptor = Saml2Utils.createSamlObject(KeyDescriptor.class);
+ signKeyDescriptor.setUse(UsageType.SIGNING);
+ final KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance();
+ signKeyDescriptor
+ .setKeyInfo(keyInfoGenerator.generate(config.getRequestorResponseSigningCredentials()));
+ idpSsoDescriptor.getKeyDescriptors().add(signKeyDescriptor);
+
+ // set IDP attribute set
+ if (config.getIdpPossibleAttributes() != null) {
+ idpSsoDescriptor.getAttributes().addAll(config.getIdpPossibleAttributes());
+
+ }
+
+ // set providable nameID formats
+ for (final String format : config.getIdpPossibleNameIdTypes()) {
+ final NameIDFormat nameIdFormat = Saml2Utils.createSamlObject(NameIDFormat.class);
+ nameIdFormat.setFormat(format);
+ idpSsoDescriptor.getNameIDFormats().add(nameIdFormat);
+
+ }
+
+ return idpSsoDescriptor;
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java
index cb4a4608..5c44af24 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java
@@ -1,92 +1,97 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.core.AttributeValue;
-import org.opensaml.xml.Configuration;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.schema.XSInteger;
-import org.opensaml.xml.schema.XSString;
-import org.opensaml.xml.schema.impl.XSIntegerBuilder;
-import org.opensaml.xml.schema.impl.XSStringBuilder;
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder;
import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSInteger;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.core.xml.schema.impl.XSIntegerBuilder;
+import org.opensaml.core.xml.schema.impl.XSStringBuilder;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeValue;
public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> {
-
- private XMLObject buildAttributeStringValue(String value) {
- XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
- XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
- stringValue.setValue(value);
- return stringValue;
- }
-
- private XMLObject buildAttributeIntegerValue(int value) {
- XSIntegerBuilder integerBuilder = (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);
- XSInteger integerValue = integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
- integerValue.setValue(value);
- return integerValue;
- }
-
- public Attribute buildStringAttribute(final String friendlyName, final String name, final String value) {
- Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class);
- attribute.setFriendlyName(friendlyName);
- attribute.setName(name);
- attribute.setNameFormat(Attribute.URI_REFERENCE);
- attribute.getAttributeValues().add(buildAttributeStringValue(value));
- return attribute;
- }
-
- public Attribute buildIntegerAttribute(final String friendlyName, final String name, final int value) {
- Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class);
- attribute.setFriendlyName(friendlyName);
- attribute.setName(name);
- attribute.setNameFormat(Attribute.URI_REFERENCE);
- attribute.getAttributeValues().add(buildAttributeIntegerValue(value));
- return attribute;
- }
-
- public Attribute buildEmptyAttribute(final String friendlyName, final String name) {
- Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class);
- attribute.setFriendlyName(friendlyName);
- attribute.setName(name);
- attribute.setNameFormat(Attribute.URI_REFERENCE);
- return attribute;
- }
- public Attribute buildLongAttribute(String friendlyName, String name, long value) {
- Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class);
- attribute.setFriendlyName(friendlyName);
- attribute.setName(name);
- attribute.setNameFormat(Attribute.URI_REFERENCE);
- attribute.getAttributeValues().add(buildAttributeIntegerValue((int) value));
- return attribute;
- }
-
+ private XMLObject buildAttributeStringValue(final String value) {
+ final XSStringBuilder stringBuilder =
+ (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
+ final XSString stringValue =
+ stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
+ stringValue.setValue(value);
+ return stringValue;
+ }
+
+ private XMLObject buildAttributeIntegerValue(final int value) {
+ final XSIntegerBuilder integerBuilder =
+ (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(
+ XSInteger.TYPE_NAME);
+ final XSInteger integerValue =
+ integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);
+ integerValue.setValue(value);
+ return integerValue;
+ }
+
+ @Override
+ public Attribute buildStringAttribute(final String friendlyName, final String name,
+ final String value) {
+ final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setName(name);
+ attribute.setNameFormat(Attribute.URI_REFERENCE);
+ attribute.getAttributeValues().add(buildAttributeStringValue(value));
+ return attribute;
+ }
+
+ @Override
+ public Attribute buildIntegerAttribute(final String friendlyName, final String name,
+ final int value) {
+ final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setName(name);
+ attribute.setNameFormat(Attribute.URI_REFERENCE);
+ attribute.getAttributeValues().add(buildAttributeIntegerValue(value));
+ return attribute;
+ }
+
+ @Override
+ public Attribute buildEmptyAttribute(final String friendlyName, final String name) {
+ final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setName(name);
+ attribute.setNameFormat(Attribute.URI_REFERENCE);
+ return attribute;
+ }
+
+ @Override
+ public Attribute buildLongAttribute(final String friendlyName, final String name,
+ final long value) {
+ final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class);
+ attribute.setFriendlyName(friendlyName);
+ attribute.setName(name);
+ attribute.setNameFormat(Attribute.URI_REFERENCE);
+ attribute.getAttributeValues().add(buildAttributeIntegerValue((int) value));
+ return attribute;
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java
deleted file mode 100644
index 817ca2f6..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import org.opensaml.saml2.common.impl.ExtensionsImpl;
-
-public class EAAFExtensionImplementation extends ExtensionsImpl {
-
- protected EAAFExtensionImplementation(String namespaceURI, String elementLocalName, String namespacePrefix) {
- super(namespaceURI, elementLocalName, namespacePrefix);
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java
deleted file mode 100644
index 431784cf..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.common.Extensions;
-
-public class EAAFRequestExtensionBuilder extends AbstractSAMLObjectBuilder<Extensions> {
-
- @Override
- public Extensions buildObject() {
- return buildObject(SAMLConstants.SAML20P_NS, Extensions.LOCAL_NAME, SAMLConstants.SAML20P_PREFIX);
-
- }
-
- @Override
- public Extensions buildObject(String namespaceURI, String localName, String namespacePrefix) {
- return new EAAFExtensionImplementation(namespaceURI, localName, namespacePrefix);
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java
deleted file mode 100644
index 33868544..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EAAFRequestedAttributeImpl;
-
-public class EAAFRequestedAttributeBuilder extends AbstractSAMLObjectBuilder<EAAFRequestedAttribute> {
-
- @Override
- public EAAFRequestedAttribute buildObject() {
- return buildObject(EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME);
- }
-
- @Override
- public EAAFRequestedAttribute buildObject(String namespaceURI, String localName, String namespacePrefix) {
- return new EAAFRequestedAttributeImpl(namespaceURI, localName,
- namespacePrefix);
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java
deleted file mode 100644
index d95adc8f..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import java.util.Map.Entry;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.Configuration;
-import org.opensaml.common.impl.AbstractSAMLObjectMarshaller;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.util.XMLHelper;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Element;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-
-public class EAAFRequestedAttributeMarshaller extends AbstractSAMLObjectMarshaller {
- protected final void marshallAttributes(final XMLObject samlElement,
- final Element domElement) throws MarshallingException {
- final EAAFRequestedAttribute requestedAttr = (EAAFRequestedAttribute) samlElement;
-
- if (requestedAttr.getName() != null) {
- domElement.setAttributeNS(null, EAAFRequestedAttribute.NAME_ATTRIB_NAME, requestedAttr.getName());
- }
-
- if (requestedAttr.getNameFormat() != null) {
- domElement.setAttributeNS(null, EAAFRequestedAttribute.NAME_FORMAT_ATTR, requestedAttr.getNameFormat());
- }
-
- if (requestedAttr.getFriendlyName() != null) {
- domElement.setAttributeNS(null, EAAFRequestedAttribute.FRIENDLY_NAME_ATT, requestedAttr.getFriendlyName());
- }
-
- if (requestedAttr.getIsRequiredXSBoolean() != null) {
- domElement.setAttributeNS(null, EAAFRequestedAttribute.IS_REQUIRED_ATTR, requestedAttr.getIsRequiredXSBoolean());
- }
-
- Attr attr;
- for (Entry<QName, String> entry : requestedAttr.getUnknownAttributes()
- .entrySet()) {
- attr = XMLHelper.constructAttribute(domElement.getOwnerDocument(),
- entry.getKey());
- attr.setValue(entry.getValue());
- domElement.setAttributeNodeNS(attr);
- if (Configuration.isIDAttribute(entry.getKey())
- || requestedAttr.getUnknownAttributes().isIDAttribute(
- entry.getKey())) {
- attr.getOwnerElement().setIdAttributeNode(attr, true);
- }
- }
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java
deleted file mode 100644
index a4515707..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.opensaml.xml.util.XMLHelper;
-import org.w3c.dom.Attr;
-
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-
-public class EAAFRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmarshaller {
- protected final void processChildElement(final XMLObject parentSAMLObject, final XMLObject childSAMLObject) throws UnmarshallingException {
- final EAAFRequestedAttribute requestedAttr = (EAAFRequestedAttribute) parentSAMLObject;
- final QName childQName = childSAMLObject.getElementQName();
-
- if ("AttributeValue".equals(childQName.getLocalPart())
- && childQName.getNamespaceURI().equals(PVPConstants.EIDAT10_SAML_NS)) {
- requestedAttr.getAttributeValues().add(childSAMLObject);
-
- } else
- super.processChildElement(parentSAMLObject, childSAMLObject);
-
- }
-
- protected final void processAttribute(final XMLObject samlObject, final Attr attribute) throws UnmarshallingException {
- final EAAFRequestedAttribute requestedAttr = (EAAFRequestedAttribute) samlObject;
- if (attribute.getLocalName().equals(EAAFRequestedAttribute.NAME_ATTRIB_NAME)) {
- requestedAttr.setName(attribute.getValue());
-
- } else if (attribute.getLocalName().equals(EAAFRequestedAttribute.NAME_FORMAT_ATTR)) {
- requestedAttr.setNameFormat(attribute.getValue());
-
- } else if (attribute.getLocalName().equals(EAAFRequestedAttribute.FRIENDLY_NAME_ATT)) {
- requestedAttr.setFriendlyName(attribute.getValue());
-
- } else if (attribute.getLocalName().equals(EAAFRequestedAttribute.IS_REQUIRED_ATTR)) {
- requestedAttr.setIsRequired(attribute.getValue());
-
- } else {
- final QName attribQName = XMLHelper.getNodeQName(attribute);
- if (attribute.isId()) {
- requestedAttr.getUnknownAttributes().registerID(attribQName);
- }
- requestedAttr.getUnknownAttributes().put(attribQName,
- attribute.getValue());
- }
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java
deleted file mode 100644
index 6e432b25..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import org.opensaml.common.impl.AbstractSAMLObjectBuilder;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes;
-import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EAAFRequestedAttributesImpl;
-
-public class EAAFRequestedAttributesBuilder extends AbstractSAMLObjectBuilder<EAAFRequestedAttributes> {
-
- @Override
- public EAAFRequestedAttributes buildObject() {
- return buildObject(EAAFRequestedAttributes.DEFAULT_ELEMENT_NAME);
- }
-
- @Override
- public EAAFRequestedAttributes buildObject(String namespaceURI, String localName, String namespacePrefix) {
- return new EAAFRequestedAttributesImpl(namespaceURI, localName,
- namespacePrefix);
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java
deleted file mode 100644
index 28d50422..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import org.opensaml.common.impl.AbstractSAMLObjectMarshaller;
-
-public class EAAFRequestedAttributesMarshaller extends AbstractSAMLObjectMarshaller {
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java
deleted file mode 100644
index b2758326..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
-
-import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.UnmarshallingException;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes;
-
-public class EAAFRequestedAttributesUnmarshaller extends AbstractSAMLObjectUnmarshaller {
- protected final void processChildElement(final XMLObject parentObject,
- final XMLObject childObject) throws UnmarshallingException {
- final EAAFRequestedAttributes attrStatement = (EAAFRequestedAttributes) parentObject;
- if (childObject instanceof EAAFRequestedAttribute) {
- attrStatement.getAttributes().add((EAAFRequestedAttribute) childObject);
-
- } else
- super.processChildElement(parentObject, childObject);
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java
new file mode 100644
index 00000000..726a2960
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import org.opensaml.saml.saml2.core.impl.ExtensionsImpl;
+
+public class EaafExtensionImplementation extends ExtensionsImpl {
+
+ protected EaafExtensionImplementation(final String namespaceUri, final String elementLocalName,
+ final String namespacePrefix) {
+ super(namespaceUri, elementLocalName, namespacePrefix);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java
new file mode 100644
index 00000000..c77193fd
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import org.opensaml.saml.common.AbstractSAMLObjectBuilder;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.Extensions;
+
+public class EaafRequestExtensionBuilder extends AbstractSAMLObjectBuilder<Extensions> {
+
+ @Override
+ public Extensions buildObject() {
+ return buildObject(SAMLConstants.SAML20P_NS, Extensions.DEFAULT_ELEMENT_LOCAL_NAME,
+ SAMLConstants.SAML20P_PREFIX);
+
+ }
+
+ @Override
+ public Extensions buildObject(final String namespaceUri, final String localName,
+ final String namespacePrefix) {
+ return new EaafExtensionImplementation(namespaceUri, localName, namespacePrefix);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java
new file mode 100644
index 00000000..fde79998
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EaafRequestedAttributeImpl;
+
+import org.opensaml.saml.common.AbstractSAMLObjectBuilder;
+
+public class EaafRequestedAttributeBuilder
+ extends AbstractSAMLObjectBuilder<EaafRequestedAttribute> {
+
+ @Override
+ public EaafRequestedAttribute buildObject() {
+ return buildObject(EaafRequestedAttribute.DEFAULT_ELEMENT_NAME);
+ }
+
+ @Override
+ public EaafRequestedAttribute buildObject(final String namespaceUri, final String localName,
+ final String namespacePrefix) {
+ return new EaafRequestedAttributeImpl(namespaceUri, localName, namespacePrefix);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java
new file mode 100644
index 00000000..4acee141
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import java.util.Map.Entry;
+
+import javax.xml.namespace.QName;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.xml.AttributeSupport;
+
+public class EaafRequestedAttributeMarshaller extends AbstractSAMLObjectMarshaller {
+ @Override
+ protected final void marshallAttributes(final XMLObject samlElement, final Element domElement)
+ throws MarshallingException {
+ final EaafRequestedAttribute requestedAttr = (EaafRequestedAttribute) samlElement;
+
+ if (requestedAttr.getName() != null) {
+ domElement.setAttributeNS(null, EaafRequestedAttribute.NAME_ATTRIB_NAME,
+ requestedAttr.getName());
+ }
+
+ if (requestedAttr.getNameFormat() != null) {
+ domElement.setAttributeNS(null, EaafRequestedAttribute.NAME_FORMAT_ATTR,
+ requestedAttr.getNameFormat());
+ }
+
+ if (requestedAttr.getFriendlyName() != null) {
+ domElement.setAttributeNS(null, EaafRequestedAttribute.FRIENDLY_NAME_ATT,
+ requestedAttr.getFriendlyName());
+ }
+
+ if (requestedAttr.getIsRequiredXsBoolean() != null) {
+ domElement.setAttributeNS(null, EaafRequestedAttribute.IS_REQUIRED_ATTR,
+ requestedAttr.getIsRequiredXsBoolean());
+ }
+
+ Attr attr;
+ for (final Entry<QName, String> entry : requestedAttr.getUnknownAttributes().entrySet()) {
+
+ attr = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());
+ attr.setValue(entry.getValue());
+ domElement.setAttributeNodeNS(attr);
+ if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey())
+ || requestedAttr.getUnknownAttributes().isIDAttribute(entry.getKey())) {
+ attr.getOwnerElement().setIdAttributeNode(attr, true);
+ }
+ }
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java
new file mode 100644
index 00000000..5313f340
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import javax.xml.namespace.QName;
+
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
+import org.w3c.dom.Attr;
+
+import net.shibboleth.utilities.java.support.xml.QNameSupport;
+
+public class EaafRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmarshaller {
+ @Override
+ protected final void processChildElement(final XMLObject parentSamlObject,
+ final XMLObject childSamlObject) throws UnmarshallingException {
+ final EaafRequestedAttribute requestedAttr = (EaafRequestedAttribute) parentSamlObject;
+ final QName childQName = childSamlObject.getElementQName();
+
+ if ("AttributeValue".equals(childQName.getLocalPart())
+ && childQName.getNamespaceURI().equals(PvpConstants.EIDAT10_SAML_NS)) {
+ requestedAttr.getAttributeValues().add(childSamlObject);
+
+ } else {
+ super.processChildElement(parentSamlObject, childSamlObject);
+ }
+
+ }
+
+ @Override
+ protected final void processAttribute(final XMLObject samlObject, final Attr attribute)
+ throws UnmarshallingException {
+ final EaafRequestedAttribute requestedAttr = (EaafRequestedAttribute) samlObject;
+ if (attribute.getLocalName().equals(EaafRequestedAttribute.NAME_ATTRIB_NAME)) {
+ requestedAttr.setName(attribute.getValue());
+
+ } else if (attribute.getLocalName().equals(EaafRequestedAttribute.NAME_FORMAT_ATTR)) {
+ requestedAttr.setNameFormat(attribute.getValue());
+
+ } else if (attribute.getLocalName().equals(EaafRequestedAttribute.FRIENDLY_NAME_ATT)) {
+ requestedAttr.setFriendlyName(attribute.getValue());
+
+ } else if (attribute.getLocalName().equals(EaafRequestedAttribute.IS_REQUIRED_ATTR)) {
+ requestedAttr.setIsRequired(attribute.getValue());
+
+ } else {
+ final QName attribQName = QNameSupport.getNodeQName(attribute);
+ if (attribute.isId()) {
+ requestedAttr.getUnknownAttributes().registerID(attribQName);
+ }
+ requestedAttr.getUnknownAttributes().put(attribQName, attribute.getValue());
+ }
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java
new file mode 100644
index 00000000..2d2de292
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EaafRequestedAttributesImpl;
+
+import org.opensaml.saml.common.AbstractSAMLObjectBuilder;
+
+public class EaafRequestedAttributesBuilder
+ extends AbstractSAMLObjectBuilder<EaafRequestedAttributes> {
+
+ @Override
+ public EaafRequestedAttributes buildObject() {
+ return buildObject(EaafRequestedAttributes.DEFAULT_ELEMENT_NAME);
+ }
+
+ @Override
+ public EaafRequestedAttributes buildObject(final String namespaceUri, final String localName,
+ final String namespacePrefix) {
+ return new EaafRequestedAttributesImpl(namespaceUri, localName, namespacePrefix);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java
new file mode 100644
index 00000000..5d1e0679
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import org.opensaml.saml.common.AbstractSAMLObjectMarshaller;
+
+public class EaafRequestedAttributesMarshaller extends AbstractSAMLObjectMarshaller {
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java
new file mode 100644
index 00000000..9934c502
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller;
+
+public class EaafRequestedAttributesUnmarshaller extends AbstractSAMLObjectUnmarshaller {
+ @Override
+ protected final void processChildElement(final XMLObject parentObject,
+ final XMLObject childObject) throws UnmarshallingException {
+ final EaafRequestedAttributes attrStatement = (EaafRequestedAttributes) parentObject;
+ if (childObject instanceof EaafRequestedAttribute) {
+ attrStatement.getAttributes().add((EaafRequestedAttribute) childObject);
+
+ } else {
+ super.processChildElement(parentObject, childObject);
+ }
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java
new file mode 100644
index 00000000..227ff30e
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java
@@ -0,0 +1,16 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.logging;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+public class PvpModuleMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/pvp_messages");
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java
index 452fa553..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
@@ -1,123 +1,167 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.message;
+import java.io.IOException;
import java.io.Serializable;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import javax.annotation.Nonnull;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
-
-/**
- * @author tlenz
- *
- */
-public class InboundMessage implements InboundMessageInterface, Serializable{
- private static final Logger log = LoggerFactory.getLogger(InboundMessage.class);
-
- private static final long serialVersionUID = 2395131650841669663L;
-
- private Element samlMessage = null;
- private boolean verified = false;
- private String entityID = null;
- private String relayState = null;
-
-
- public EntityDescriptor getEntityMetadata(IPVPMetadataProvider metadataProvider) throws NoMetadataInformationException {
- try {
- if (metadataProvider == null)
- throw new NullPointerException("No PVP MetadataProvider found.");
-
- return metadataProvider.getEntityDescriptor(this.entityID);
-
- } catch (MetadataProviderException e) {
- log.warn("No Metadata for EntitiyID " + entityID);
- throw new NoMetadataInformationException();
- }
- }
-
- /**
- * @param entitiyID the entitiyID to set
- */
- public void setEntityID(String entitiyID) {
- this.entityID = entitiyID;
- }
-
- public void setVerified(boolean verified) {
- this.verified = verified;
- }
-
- /**
- * @param relayState the relayState to set
- */
- public void setRelayState(String relayState) {
- this.relayState = relayState;
- }
-
- public void setSAMLMessage(Element msg) {
- this.samlMessage = msg;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#getRelayState()
- */
- @Override
- public String getRelayState() {
- return relayState;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#getEntityID()
- */
- @Override
- public String getEntityID() {
- return entityID;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#isVerified()
- */
- @Override
- public boolean isVerified() {
- return verified;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#getInboundMessage()
- */
- @Override
- public Element getInboundMessage() {
- return samlMessage;
- }
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+public class InboundMessage implements InboundMessageInterface, Serializable {
+ private static final Logger log = LoggerFactory.getLogger(InboundMessage.class);
+
+ private static final long serialVersionUID = 2395131650841669663L;
+
+ private transient Element samlMessage = null;
+ private boolean verified = false;
+ private String entityID = null;
+ private String relayState = null;
+
+ private String serializedSamlMessage;
+
+ /**
+ * Get SAML2 metadata for Entity that sends this request.
+ *
+ * @param metadataProvider Metadataprovider
+ * @return EntityDescriptor from metadata
+ * @throws NoMetadataInformationException In case of an error
+ */
+ public EntityDescriptor getEntityMetadata(@Nonnull final IPvp2MetadataProvider metadataProvider)
+ throws NoMetadataInformationException {
+ try {
+ return metadataProvider.getEntityDescriptor(this.entityID);
+
+ } catch (final ResolverException e) {
+ log.warn("No Metadata for EntitiyID " + entityID);
+ throw new NoMetadataInformationException();
+
+ }
+ }
+
+ /**
+ * Set EntitId of requester.
+ *
+ * @param entitiyID the entitiyID to set
+ */
+ public void setEntityID(final String entitiyID) {
+ this.entityID = entitiyID;
+ }
+
+ public void setVerified(final boolean verified) {
+ this.verified = verified;
+ }
+
+ /**
+ * Set relayState from requester.
+ *
+ * @param relayState the relayState to set
+ */
+ public void setRelayState(final String relayState) {
+ this.relayState = relayState;
+ }
+
+ /**
+ * Set full SAML2 message.
+ *
+ * @param msg message
+ */
+ public void setSamlMessage(final Element msg) {
+ this.samlMessage = msg;
+ try {
+ this.serializedSamlMessage = DomUtils.serializeNode(msg);
+
+ } catch (TransformerException | IOException e) {
+ log.warn("Can not serialize message", e);
+
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#
+ * getRelayState()
+ */
+ @Override
+ public String getRelayState() {
+ return relayState;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#
+ * getEntityID()
+ */
+ @Override
+ public String getEntityID() {
+ return entityID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#
+ * isVerified()
+ */
+ @Override
+ public boolean isVerified() {
+ return verified;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#
+ * getInboundMessage()
+ */
+ @Override
+ public Element getInboundMessage() {
+ if (this.samlMessage != null) {
+ return samlMessage;
+
+ } else {
+ try {
+ return DomUtils.parseDocument(serializedSamlMessage, false, null, null).getDocumentElement();
+
+ } catch (SAXException | IOException | ParserConfigurationException e) {
+ throw new RuntimeException(e);
+
+ }
+
+ }
+
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java
deleted file mode 100644
index 9c9c913d..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.message;
-
-
-import org.opensaml.Configuration;
-import org.opensaml.xml.io.Unmarshaller;
-import org.opensaml.xml.io.UnmarshallerFactory;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.opensaml.xml.signature.SignableXMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PVPSProfileRequest extends InboundMessage{
- private static final Logger log = LoggerFactory.getLogger(PVPSProfileRequest.class);
-
- private static final long serialVersionUID = 8613921176727607896L;
-
- private String binding = null;
-
- public PVPSProfileRequest(SignableXMLObject inboundMessage, String binding) {
- setSAMLMessage(inboundMessage.getDOM());
- this.binding = binding;
-
- }
-
- public String getRequestBinding() {
- return binding;
- }
-
- public SignableXMLObject getSamlRequest() {
- UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
- Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
-
- try {
- return (SignableXMLObject) unmashaller.unmarshall(getInboundMessage());
-
- } catch (UnmarshallingException e) {
- log.warn("AuthnRequest Unmarshaller error", e);
- return null;
- }
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java
deleted file mode 100644
index 107aa731..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.message;
-
-import org.opensaml.Configuration;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.xml.io.Unmarshaller;
-import org.opensaml.xml.io.UnmarshallerFactory;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PVPSProfileResponse extends InboundMessage {
-
- private static final Logger log = LoggerFactory.getLogger(PVPSProfileResponse.class);
-
- private static final long serialVersionUID = -1133012928130138501L;
-
- public PVPSProfileResponse(StatusResponseType response) {
- setSAMLMessage(response.getDOM());
- }
-
- public StatusResponseType getResponse() {
- UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
- Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
-
- try {
- return (StatusResponseType) unmashaller.unmarshall(getInboundMessage());
-
- } catch (UnmarshallingException e) {
- log.warn("AuthnResponse Unmarshaller error", e);
- return null;
- }
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java
new file mode 100644
index 00000000..c6068769
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.message;
+
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallerFactory;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.xmlsec.signature.SignableXMLObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PvpSProfileRequest extends InboundMessage {
+ private static final Logger log = LoggerFactory.getLogger(PvpSProfileRequest.class);
+
+ private static final long serialVersionUID = 8613921176727607896L;
+
+ private String binding = null;
+
+ /**
+ * PVP2 S-Profil request DAO.
+ *
+ * @param inboundMessage SAML2 request object
+ * @param binding Used SAML2 binding
+ */
+ public PvpSProfileRequest(final SignableXMLObject inboundMessage, final String binding) {
+ setSamlMessage(inboundMessage.getDOM());
+ this.binding = binding;
+
+ }
+
+ public String getRequestBinding() {
+ return binding;
+ }
+
+ /**
+ * Get SAML2 request object.
+ *
+ * @return
+ */
+ public SignableXMLObject getSamlRequest() {
+ final UnmarshallerFactory unmarshallerFactory =
+ XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
+ final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
+
+ try {
+ return (SignableXMLObject) unmashaller.unmarshall(getInboundMessage());
+
+ } catch (final UnmarshallingException e) {
+ log.warn("AuthnRequest Unmarshaller error", e);
+ return null;
+ }
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java
new file mode 100644
index 00000000..4ad21fbc
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.message;
+
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallerFactory;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PvpSProfileResponse extends InboundMessage {
+
+ private static final Logger log = LoggerFactory.getLogger(PvpSProfileResponse.class);
+
+ private static final long serialVersionUID = -1133012928130138501L;
+
+ public PvpSProfileResponse(final StatusResponseType response) {
+ setSamlMessage(response.getDOM());
+ }
+
+ /**
+ * Get SAML2 Response object.
+ *
+ * @return
+ */
+ public StatusResponseType getResponse() {
+ final UnmarshallerFactory unmarshallerFactory =
+ XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
+ final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
+
+ try {
+ return (StatusResponseType) unmashaller.unmarshall(getInboundMessage());
+
+ } catch (final UnmarshallingException e) {
+ log.warn("AuthnResponse Unmarshaller error", e);
+ return null;
+ }
+
+ }
+
+}
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 08ef26ab..40448b45 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
@@ -1,470 +1,530 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Timer;
-import javax.xml.namespace.QName;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.RoleDescriptor;
-import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider;
-import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.naming.ConfigurationException;
import at.gv.egiz.components.spring.api.IDestroyableObject;
import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing;
-import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpAddableChainingMetadataProvider;
import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
-public abstract class AbstractChainingMetadataProvider extends SimpleMetadataProvider
- implements ObservableMetadataProvider, IGarbageCollectorProcessing,
- IRefreshableMetadataProvider, IDestroyableObject, IPVPMetadataProvider {
-
- private static final Logger log = LoggerFactory.getLogger(AbstractChainingMetadataProvider.class);
-
- private MetadataProvider internalProvider = null;
- private static Object mutex = new Object();
- private Timer timer = null;
-
-
- public AbstractChainingMetadataProvider() {
- internalProvider = new ChainingMetadataProvider();
-
- }
-
- public final Timer getTimer() {
- return this.timer;
-
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#runGarbageCollector()
- */
- @Override
- public void runGarbageCollector() {
- synchronized (mutex) {
- /**add new Metadataprovider or remove Metadataprovider which are not in use any more.**/
- try {
- log.trace("Check consistence of PVP2X metadata");
- addAndRemoveMetadataProvider();
-
- } catch (EAAFConfigurationException e) {
- log.error("Access to MOA-ID configuration FAILED.", e);
-
- }
- }
-
- }
-
- public void fullyDestroy() {
- internalDestroy();
-
- }
-
- @Override
- public synchronized boolean refreshMetadataProvider(String entityID) {
- try {
- //check if metadata provider is already loaded
- try {
- if (internalProvider.getEntityDescriptor(entityID) != null)
- return true;
-
- } catch (MetadataProviderException e) {}
-
-
- //reload metadata provider
- String metadataURL = getMetadataURL(entityID);
- if (StringUtils.isNotEmpty(metadataURL)) {
- Map<String, HTTPMetadataProvider> actuallyLoadedProviders = getAllActuallyLoadedProviders();
-
- // check if MetadataProvider is actually loaded
- if (actuallyLoadedProviders.containsKey(metadataURL)) {
- actuallyLoadedProviders.get(metadataURL).refresh();
- log.info("SAML2 metadata for service provider: "
- + entityID + " is refreshed.");
- return true;
-
- } else {
- //load new Metadata Provider
- if (timer == null)
- timer = new Timer(true);
-
- ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
- chainProvider.addMetadataProvider(createNewMetadataProvider(entityID));
-
- emitChangeEvent();
- log.info("SAML2 metadata for service provider: "
- + entityID + " is added.");
- return true;
-
- }
-
- } else
- log.debug("Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: " + entityID);
-
- } catch (MetadataProviderException e) {
- log.warn("Refresh SAML2 metadata for service provider: "
- + entityID + " FAILED.", e);
-
- } catch (IOException e) {
- log.warn("Refresh SAML2 metadata for service provider: "
- + entityID + " FAILED.", e);
-
- } catch (EAAFConfigurationException e) {
- log.warn("Refresh SAML2 metadata for service provider: "
- + entityID + " FAILED.", e);
-
- } catch (CertificateException e) {
- log.warn("Refresh SAML2 metadata for service provider: "
- + entityID + " FAILED.", e);
-
- }
-
- return false;
-
- }
-
- public void internalDestroy() {
- if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) {
- log.info("Destrorying PVP-Authentication MetaDataProvider.");
- ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
-
- List<MetadataProvider> providers = chainProvider.getProviders();
- for (MetadataProvider provider : providers) {
- if (provider instanceof HTTPMetadataProvider) {
- HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider;
- log.debug("Destroy HTTPMetadataProvider +" + httpprovider.getMetadataURI());
- httpprovider.destroy();
-
- } else {
- log.warn("MetadataProvider can not be destroyed.");
- }
- }
-
- internalProvider = new ChainingMetadataProvider();
-
- if (timer != null)
- timer.cancel();
-
- } else {
- log.warn("ReInitalize MOAMetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy");
- }
- }
-
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#requireValidMetadata()
- */
- @Override
- public boolean requireValidMetadata() {
- return internalProvider.requireValidMetadata();
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#setRequireValidMetadata(boolean)
- */
- @Override
- public void setRequireValidMetadata(boolean requireValidMetadata) {
- internalProvider.setRequireValidMetadata(requireValidMetadata);
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getMetadataFilter()
- */
- @Override
- public MetadataFilter getMetadataFilter() {
- return internalProvider.getMetadataFilter();
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#setMetadataFilter(org.opensaml.saml2.metadata.provider.MetadataFilter)
- */
- @Override
- public void setMetadataFilter(MetadataFilter newFilter)
- throws MetadataProviderException {
- internalProvider.setMetadataFilter(newFilter);
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getMetadata()
- */
- @Override
- public XMLObject getMetadata() throws MetadataProviderException {
- return internalProvider.getMetadata();
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getEntitiesDescriptor(java.lang.String)
- */
- @Override
- public EntitiesDescriptor getEntitiesDescriptor(String entitiesID)
- throws MetadataProviderException {
- EntitiesDescriptor entitiesDesc = null;
- try {
- entitiesDesc = internalProvider.getEntitiesDescriptor(entitiesID);
-
- if (entitiesDesc == null) {
- log.debug("Can not find PVP metadata for entityID: " + entitiesID
- + " Start refreshing process ...");
- if (refreshMetadataProvider(entitiesID))
- return internalProvider.getEntitiesDescriptor(entitiesID);
-
- }
-
- } catch (MetadataProviderException e) {
- log.debug("Can not find PVP metadata for entityID: " + entitiesID
- + " Start refreshing process ...");
- if (refreshMetadataProvider(entitiesID))
- return internalProvider.getEntitiesDescriptor(entitiesID);
-
- }
-
- return entitiesDesc;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getEntityDescriptor(java.lang.String)
- */
- @Override
- public EntityDescriptor getEntityDescriptor(String entityID)
- throws MetadataProviderException {
- EntityDescriptor entityDesc = null;
- try {
- entityDesc = internalProvider.getEntityDescriptor(entityID);
- if (entityDesc == null) {
- log.debug("Can not find PVP metadata for entityID: " + entityID
- + " Start refreshing process ...");
- if (refreshMetadataProvider(entityID))
- return internalProvider.getEntityDescriptor(entityID);
-
- }
-
- } catch (MetadataProviderException e) {
- log.debug("Can not find PVP metadata for entityID: " + entityID
- + " Start refreshing process ...");
- if (refreshMetadataProvider(entityID))
- return internalProvider.getEntityDescriptor(entityID);
-
- }
-
-// if (entityDesc != null)
-// lastAccess.put(entityID, new Date());
-
- return entityDesc;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getRole(java.lang.String, javax.xml.namespace.QName)
- */
- @Override
- public List<RoleDescriptor> getRole(String entityID, QName roleName)
- throws MetadataProviderException {
- List<RoleDescriptor> result = internalProvider.getRole(entityID, roleName);
-
-// if (result != null)
-// lastAccess.put(entityID, new Date());
-
- return result;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getRole(java.lang.String, javax.xml.namespace.QName, java.lang.String)
- */
- @Override
- public RoleDescriptor getRole(String entityID, QName roleName,
- String supportedProtocol) throws MetadataProviderException {
- RoleDescriptor result = internalProvider.getRole(entityID, roleName, supportedProtocol);
-
-// if (result != null)
-// lastAccess.put(entityID, new Date());
-
- return result;
- }
-
- /* (non-Javadoc)
- * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider#getObservers()
- */
- @Override
- public List<Observer> getObservers() {
- return ((ChainingMetadataProvider) internalProvider).getObservers();
- }
-
-
- /**
- * Get the URL to metadata for a specific entityID
- *
- * @param entityId
- * @return
- * @throws EAAFConfigurationException
- */
- protected abstract String getMetadataURL(String entityId) throws EAAFConfigurationException;
-
- /**
- * Creates a new implementation specific SAML2 metadata provider
- *
- * @param entityId
- * @return
- * @throws EAAFConfigurationException
- * @throws IOException
- * @throws CertificateException
- * @throws ConfigurationException
- */
- protected abstract MetadataProvider createNewMetadataProvider(String entityId) throws EAAFConfigurationException, IOException, CertificateException;
-
- /**
- * Get a List of metadata URLs for all SAML2 SPs from configuration
- *
- * @throws EAAFConfigurationException
- */
- protected abstract List<String> getAllMetadataURLsFromConfiguration() throws EAAFConfigurationException;
-
-
- protected void emitChangeEvent() {
- if ((getObservers() == null) || (getObservers().size() == 0)) {
- return;
- }
-
- List<Observer> tempObserverList = new ArrayList<Observer>(getObservers());
- for (ObservableMetadataProvider.Observer observer : tempObserverList)
- if (observer != null)
- observer.onEvent(this);
- }
-
- private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() {
- Map<String, HTTPMetadataProvider> loadedproviders = new HashMap<String, HTTPMetadataProvider>();
- ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
-
- //make a Map of all actually loaded HTTPMetadataProvider
- List<MetadataProvider> providers = chainProvider.getProviders();
- for (MetadataProvider provider : providers) {
- if (provider instanceof HTTPMetadataProvider) {
- HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider;
- loadedproviders.put(httpprovider.getMetadataURI(), httpprovider);
-
- }
- }
-
- return loadedproviders;
- }
-
- private void addAndRemoveMetadataProvider() throws EAAFConfigurationException {
- if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) {
- log.info("Reload MOAMetaDataProvider.");
-
- /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException)
- *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/
- Map<String, MetadataProvider> providersinuse = new HashMap<String, MetadataProvider>();
- ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
-
- //get all actually loaded metadata providers
- Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders();
-
- /* TODO: maybe add metadata provider destroy after timeout.
- * But could be a problem if one Metadataprovider load an EntitiesDescriptor
- * with more the multiple EntityDescriptors. If one of this EntityDesciptors
- * are expired the full EntitiesDescriptor is removed.
- *
- * Timeout requires a better solution in this case!
- */
-
- //load all SAML2 SPs form configuration and
- //compare actually loaded Providers with configured SAML2 SPs
- List<String> allMetadataURLs = getAllMetadataURLsFromConfiguration();
-
- if (allMetadataURLs != null) {
- Iterator<String> metadataURLInterator = allMetadataURLs.iterator();
- while (metadataURLInterator.hasNext()) {
- String metadataurl = metadataURLInterator.next();
- try {
- if (StringUtils.isNotEmpty(metadataurl)) {
- if (loadedproviders.containsKey(metadataurl)) {
- // SAML2 SP is actually loaded, to nothing
- providersinuse.put(metadataurl, loadedproviders.get(metadataurl));
- loadedproviders.remove(metadataurl);
-
- }
- }
- } catch (Throwable e) {
- log.error(
- "Failed to add Metadata (unhandled reason: " + e.getMessage(), e);
-
- }
- }
- }
-
- //remove all actually loaded MetadataProviders with are not in ConfigurationDB any more
- Collection<HTTPMetadataProvider> notusedproviders = loadedproviders.values();
- for (HTTPMetadataProvider provider : notusedproviders) {
- String metadataurl = provider.getMetadataURI();
- try {
- provider.destroy();
-
- /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException)
- *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/
- //chainProvider.removeMetadataProvider(provider);
- log.info("Remove not used MetadataProvider with MetadataURL " + metadataurl);
-
- } catch (Throwable e) {
- log.error("HTTPMetadataProvider with URL " + metadataurl
- + " can not be removed from the list of actually loaded Providers.", e);
-
- }
-
- }
-
- try {
- chainProvider.setProviders(new ArrayList<MetadataProvider>(providersinuse.values()));
- emitChangeEvent();
-
- } catch (MetadataProviderException e) {
- log.warn("ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy", e);
-
- }
-
- } else
- log.warn("ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy");
-
- }
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.saml.metadata.resolver.ClearableMetadataResolver;
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+@Slf4j
+public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing,
+ IRefreshableMetadataProvider, IPvpAddableChainingMetadataProvider,
+ IDestroyableObject, IPvp2MetadataProvider, ClearableMetadataResolver {
+
+ @Nonnull
+ @NonnullElements
+ private final List<MetadataResolver> internalResolvers;
+ private DateTime lastRefeshTimestamp;
+ private boolean lastRefeshSuccessful;
+ private static Object mutex = new Object();
+
+ /**
+ * Build a chaining metadata resolver that requires valid metadata.
+ *
+ */
+ public AbstractChainingMetadataProvider() {
+ internalResolvers = Collections.synchronizedList(new ArrayList<>());
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#
+ * runGarbageCollector()
+ */
+ @Override
+ public void runGarbageCollector() {
+ synchronized (mutex) {
+ /*
+ * add new Metadataprovider or remove Metadataprovider which are not in use any
+ * more.
+ */
+ try {
+ log.trace("Check consistence of PVP2X metadata");
+ addAndRemoveMetadataProvider();
+
+ } catch (final EaafConfigurationException e) {
+ log.error("Access to MOA-ID configuration FAILED.", e);
+
+ }
+ }
+
+ }
+
+ @Override
+ public void fullyDestroy() {
+ internalDestroy();
+
+ }
+
+ @Override
+ public synchronized boolean refreshMetadataProvider(final String entityId) {
+ try {
+ //if (resolveEntityDescriporForRefesh(entityId)) {
+ // return true;
+ //
+ //}
+
+ // reload metadata provider
+ final String metadataUrl = getMetadataUrl(entityId);
+ if (StringUtils.isNotEmpty(metadataUrl)) {
+ final Map<String, MetadataResolver> actuallyLoadedResolver =
+ getAllActuallyLoadedResolvers();
+
+ // check if MetadataProvider is actually loaded
+ final MetadataResolver loadedResover = actuallyLoadedResolver.get(metadataUrl);
+ if (loadedResover instanceof RefreshableMetadataResolver) {
+ try {
+ ((RefreshableMetadataResolver) loadedResover).refresh();
+ log.info("SAML2 metadata for service provider: {} is refreshed.", entityId);
+ return true;
+
+ } catch (final ResolverException e) {
+ log.info("Can not refresh SAML2 metadata for entityId: {}. Reason: {}", entityId, e.getMessage());
+ destroyMetadataResolver(loadedResover);
+ internalResolvers.remove(loadedResover);
+
+ }
+
+ } else {
+ // load new Metadata Provider
+ internalResolvers.add(createNewMetadataProvider(metadataUrl));
+
+ log.info("SAML2 metadata for service provider: {} is added.", entityId);
+ return true;
+
+ }
+
+ } else {
+ log.debug(
+ "Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: {}", entityId);
+ }
+
+ } catch (final IOException | EaafConfigurationException | CertificateException e) {
+ log.warn("Refresh SAML2 metadata for service provider: " + entityId + " FAILED.", e);
+
+ }
+
+ return false;
+
+ }
+
+
+ @Override
+ public final MetadataFilter getMetadataFilter() {
+ log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(),
+ MetadataFilter.class.getName());
+ return null;
+ }
+
+ @Override
+ public final void setMetadataFilter(final MetadataFilter newFilter) {
+ log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(),
+ MetadataFilter.class.getName());
+ throw new UnsupportedOperationException(
+ "Metadata filters are not supported on AbstractChainingMetadataProvider");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#
+ * getEntityDescriptor( java.lang.String)
+ */
+ @Override
+ public final EntityDescriptor getEntityDescriptor(final String entityID)
+ throws ResolverException {
+ EntityDescriptor entityDesc = null;
+ try {
+ entityDesc = resolveEntityDescripor(entityID);
+ if (entityDesc == null) {
+ log.debug("Can not find PVP metadata for entityID: " + entityID
+ + " Start refreshing process ...");
+ if (refreshMetadataProvider(entityID)) {
+ return resolveEntityDescripor(entityID);
+ }
+ }
+
+ } catch (final ResolverException e) {
+ log.debug(
+ "Can not find PVP metadata for entityID: " + entityID + " Start refreshing process ...");
+ if (refreshMetadataProvider(entityID)) {
+ return resolveEntityDescripor(entityID);
+
+ }
+
+ }
+
+ return entityDesc;
+ }
+
+ @Override
+ @Nullable
+ public final EntityDescriptor resolveSingle(@Nullable final CriteriaSet criteria)
+ throws ResolverException {
+ EntityDescriptor result = internalResolveSingle(criteria);
+ if (result == null && criteria != null) {
+ final EntityIdCriterion entityIdCriteria = criteria.get(EntityIdCriterion.class);
+ if (entityIdCriteria != null
+ && refreshMetadataProvider(entityIdCriteria.getEntityId())) {
+ log.debug("Can not find PVP metadata for entityID: {}. Metadata refreshing was done ... ",
+ entityIdCriteria.getEntityId());
+ result = internalResolveSingle(criteria);
+
+ }
+ }
+
+ return result;
+
+ }
+
+ @Override
+ @Nonnull
+ public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria)
+ throws ResolverException {
+ Iterable<EntityDescriptor> result = internalResolve(criteria);
+ if (criteria != null) {
+ final EntityIdCriterion entityIdCriteria = criteria.get(EntityIdCriterion.class);
+ if (!result.iterator().hasNext() && entityIdCriteria != null
+ && refreshMetadataProvider(entityIdCriteria.getEntityId())) {
+ log.debug("Can not find PVP metadata for entityID: {}. Metadata refreshing was done ... ",
+ entityIdCriteria.getEntityId());
+ result = internalResolve(criteria);
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public final void clear() throws ResolverException {
+ for (final MetadataResolver resolver : internalResolvers) {
+ if (resolver instanceof ClearableMetadataResolver) {
+ ((ClearableMetadataResolver) resolver).clear();
+ }
+ }
+ }
+
+ @Override
+ public final void clear(String entityID) throws ResolverException {
+ for (final MetadataResolver resolver : internalResolvers) {
+ if (resolver instanceof ClearableMetadataResolver) {
+ ((ClearableMetadataResolver) resolver).clear(entityID);
+ }
+ }
+ }
+
+ @Override
+ public final void refresh() throws ResolverException {
+ this.lastRefeshSuccessful = false;
+ for (final MetadataResolver resolver : internalResolvers) {
+ if (resolver instanceof RefreshableMetadataResolver) {
+ ((RefreshableMetadataResolver) resolver).refresh();
+
+ }
+ }
+
+ this.lastRefeshTimestamp = DateTime.now();
+ this.lastRefeshSuccessful = true;
+ }
+
+ @Override
+ @Nullable
+ public final DateTime getLastUpdate() {
+ DateTime ret = null;
+ for (final MetadataResolver resolver : internalResolvers) {
+ if (resolver instanceof RefreshableMetadataResolver) {
+ final DateTime lastUpdate = ((RefreshableMetadataResolver) resolver).getLastUpdate();
+ if (ret == null || ret.isBefore(lastUpdate)) {
+ ret = lastUpdate;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ @Override
+ @Nullable
+ public final DateTime getLastRefresh() {
+ DateTime ret = null;
+ for (final MetadataResolver resolver : internalResolvers) {
+ if (resolver instanceof RefreshableMetadataResolver) {
+ final DateTime lastRefresh = ((RefreshableMetadataResolver) resolver).getLastRefresh();
+ if (ret == null || ret.isBefore(lastRefresh)) {
+ ret = lastRefresh;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ @Override
+ public final DateTime getLastSuccessfulRefresh() {
+ return this.lastRefeshTimestamp;
+
+ }
+
+ @Override
+ public final Boolean wasLastRefreshSuccess() {
+ return this.lastRefeshSuccessful;
+
+ }
+
+ @Override
+ public final boolean isRequireValidMetadata() {
+ log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver");
+ return false;
+ }
+
+ @Override
+ public final void setRequireValidMetadata(final boolean requireValidMetadata) {
+ throw new UnsupportedOperationException(
+ "Setting requireValidMetadata is not supported on chaining resolver");
+ }
+
+ @Override
+ public final String getId() {
+ return getMetadataProviderId();
+
+ }
+
+ @Override
+ public final void addMetadataResolverIntoChain(MetadataResolver resolver) {
+ internalResolvers.add(resolver);
+
+ }
+
+ /**
+ * Get the URL to metadata for a specific entityID.
+ *
+ * @param entityId EntityId
+ * @return URL to metadata
+ * @throws EaafConfigurationException In case of an error
+ */
+ protected abstract String getMetadataUrl(String entityId) throws EaafConfigurationException;
+
+ /**
+ * Creates a new implementation specific SAML2 metadata provider.
+ *
+ * @param entityId EntityId
+ * @return MetadataResolver
+ * @throws EaafConfigurationException In case of an error
+ * @throws IOException In case of an error
+ * @throws CertificateException In case of an error
+ * @throws ConfigurationException In case of an error
+ */
+ protected abstract MetadataResolver createNewMetadataProvider(String entityId)
+ throws EaafConfigurationException, IOException, CertificateException;
+
+ /**
+ * Get a List of metadata URLs for all SAML2 SPs from configuration.
+ *
+ * @throws EaafConfigurationException In case of an error
+ */
+ @Nonnull
+ protected abstract List<String> getAllMetadataUrlsFromConfiguration()
+ throws EaafConfigurationException;
+
+ /**
+ * Get a Id for this metadata provider.
+ *
+ * @return
+ */
+ @Nonnull
+ protected abstract String getMetadataProviderId();
+
+ protected final MetadataResolver getMetadataResolver() {
+ log.warn("{} does NOT support 'getMetadataResolver'", AbstractChainingMetadataProvider.class.getName());
+ return null;
+
+ }
+
+ private Map<String, MetadataResolver> getAllActuallyLoadedResolvers() {
+ final Map<String, MetadataResolver> loadedproviders =
+ new HashMap<>();
+
+ // make a Map of all actually loaded HTTPMetadataProvider
+ for (final MetadataResolver resolver : internalResolvers) {
+ loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver);
+
+ }
+
+ return loadedproviders;
+ }
+
+ private void addAndRemoveMetadataProvider() throws EaafConfigurationException {
+ log.info("EAAF chaining metadata resolver starting internal managment task .... ");
+
+ // get all actually loaded metadata providers
+ final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers();
+
+ /*
+ * TODO: maybe add metadata provider destroy after timeout. But could be a
+ * problem if one Metadataprovider load an EntitiesDescriptor with more the
+ * multiple EntityDescriptors. If one of this EntityDesciptors are expired the
+ * full EntitiesDescriptor is removed.
+ *
+ * Timeout requires a better solution in this case!
+ */
+
+ // load all SAML2 SPs form configuration and
+ // compare actually loaded Providers with configured SAML2 SPs
+ final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration();
+
+ final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator();
+ while (metadataUrlInterator.hasNext()) {
+ final String metadataurl = metadataUrlInterator.next();
+ try {
+ if (StringUtils.isNotEmpty(metadataurl)
+ && loadedproviders.containsKey(metadataurl)) {
+ // SAML2 SP is actually loaded, to nothing
+ loadedproviders.remove(metadataurl);
+
+ }
+ } catch (final Throwable e) {
+ log.error("Failed to add Metadata (unhandled reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ // remove all actually loaded MetadataProviders with are not in ConfigurationDB
+ // any more
+ final Collection<MetadataResolver> notusedproviders = loadedproviders.values();
+ for (final MetadataResolver resolver : notusedproviders) {
+ log.info("Remove not used MetadataProvider with MetadataURL " + resolver.getId());
+ destroyMetadataResolver(resolver);
+ internalResolvers.remove(resolver);
+
+ }
+
+ }
+
+ private EntityDescriptor resolveEntityDescripor(String entityId) throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new EntityIdCriterion(entityId));
+ return internalResolveSingle(criteria);
+
+ }
+
+ private void destroyMetadataResolver(MetadataResolver resolver) {
+ if (resolver instanceof AbstractMetadataResolver) {
+ final AbstractMetadataResolver httpprovider = (AbstractMetadataResolver) resolver;
+ log.debug("Destroy metadata resolver with id: {}", httpprovider.getId());
+ httpprovider.destroy();
+
+ } else {
+ log.warn("Metadata resolver: {} can not be destroyed. Reason: unsupported type: {}",
+ resolver.getId(), resolver.getClass().getName());
+
+ }
+ }
+
+ /**
+ * Close metadata provider and remove all loaded metadata.
+ *
+ */
+ private void internalDestroy() {
+ log.info("Destroying chained metadata resolvers ...");
+
+ for (final MetadataResolver resolver : internalResolvers) {
+ destroyMetadataResolver(resolver);
+ }
+
+ internalResolvers.clear();
+
+ }
+
+ @Nullable
+ private EntityDescriptor internalResolveSingle(@Nullable final CriteriaSet criteria)
+ throws ResolverException {
+ for (final MetadataResolver resolver : internalResolvers) {
+ try {
+ final EntityDescriptor descriptors = resolver.resolveSingle(criteria);
+ if (descriptors != null) {
+ return descriptors;
+ }
+
+ } catch (final ResolverException e) {
+ continue;
+
+ }
+ }
+
+ return null;
+
+ }
+
+ @Nonnull
+ private Iterable<EntityDescriptor> internalResolve(@Nullable final CriteriaSet criteria)
+ throws ResolverException {
+ for (final MetadataResolver resolver : internalResolvers) {
+ try {
+ final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria);
+ if (descriptors != null && descriptors.iterator().hasNext()) {
+ return descriptors;
+
+ }
+
+ } catch (final ResolverException e) {
+ continue;
+
+ }
+ }
+
+ return Collections.emptyList();
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java
deleted file mode 100644
index 06065a82..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.opensaml.saml2.metadata.provider.FilterException;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * @author tlenz
- *
- */
-public class MetadataFilterChain implements MetadataFilter {
- private static final Logger log = LoggerFactory.getLogger(MetadataFilterChain.class);
-
-
- private List<MetadataFilter> filters = new ArrayList<MetadataFilter>();
-
- /**
- * Return all actually used Metadata filters
- *
- * @return List of Metadata filters
- */
- public List<MetadataFilter> getFilters() {
- return filters;
- }
-
- /**
- * Add a new Metadata filter to filterchain
- *
- * @param filter
- */
- public void addFilter(MetadataFilter filter) {
- filters.add(filter);
- }
-
-
- /* (non-Javadoc)
- * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject)
- */
- @Override
- public void doFilter(XMLObject arg0) throws FilterException {
- for (MetadataFilter filter : filters) {
- log.trace("Use EAAFMetadataFilter " + filter.getClass().getName());
- filter.doFilter(arg0);
- }
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java
new file mode 100644
index 00000000..d2b861dc
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java
@@ -0,0 +1,115 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
+
+import org.joda.time.DateTime;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+@Slf4j
+public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider, IRefreshableMetadataProvider {
+
+ private final ExtendedRefreshableMetadataResolver internalProvider;
+
+ public PvpMetadataResolverAdapter(ExtendedRefreshableMetadataResolver provider) {
+ this.internalProvider = provider;
+ }
+
+ @Override
+ public void refresh() throws ResolverException {
+ internalProvider.refresh();
+
+ }
+
+ @Override
+ public DateTime getLastRefresh() {
+ return internalProvider.getLastRefresh();
+
+ }
+
+ @Override
+ public DateTime getLastUpdate() {
+ return internalProvider.getLastUpdate();
+ }
+
+ @Override
+ public boolean isRequireValidMetadata() {
+ return internalProvider.isRequireValidMetadata();
+
+ }
+
+ @Override
+ public void setRequireValidMetadata(boolean requireValidMetadata) {
+ internalProvider.setRequireValidMetadata(requireValidMetadata);
+
+ }
+
+ @Override
+ public MetadataFilter getMetadataFilter() {
+ return internalProvider.getMetadataFilter();
+
+ }
+
+ @Override
+ public void setMetadataFilter(MetadataFilter newFilter) {
+ internalProvider.setMetadataFilter(newFilter);
+
+ }
+
+ @Override
+ public Iterable<EntityDescriptor> resolve(CriteriaSet criteria) throws ResolverException {
+ return internalProvider.resolve(criteria);
+ }
+
+ @Override
+ public EntityDescriptor resolveSingle(CriteriaSet criteria) throws ResolverException {
+ return internalProvider.resolveSingle(criteria);
+
+ }
+
+ @Override
+ public String getId() {
+ return internalProvider.getId();
+ }
+
+ @Override
+ public EntityDescriptor getEntityDescriptor(String entityId) throws ResolverException {
+ final CriteriaSet criteria = new CriteriaSet();
+ criteria.add(new EntityIdCriterion(entityId));
+ return internalProvider.resolveSingle(criteria);
+
+ }
+
+ @Override
+ public DateTime getLastSuccessfulRefresh() {
+ return internalProvider.getLastSuccessfulRefresh();
+ }
+
+ @Override
+ public Boolean wasLastRefreshSuccess() {
+ return internalProvider.wasLastRefreshSuccess();
+ }
+
+ @Override
+ public boolean refreshMetadataProvider(String entityID) {
+ try {
+ log.trace("Refeshing metadata-provider: {} ... ", getId());
+ internalProvider.refresh();
+ return true;
+
+ } catch (final ResolverException e) {
+ log.warn("Refreshing of metadata-provider: {} failed. Reason: {}",
+ getId(), e.getMessage());
+ return false;
+
+ }
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java
new file mode 100644
index 00000000..0b505e56
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java
@@ -0,0 +1,278 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
+
+import java.io.IOException;
+import java.util.Timer;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.PostConstruct;
+import javax.net.ssl.SSLHandshakeException;
+
+import at.gv.egiz.components.spring.api.IDestroyableObject;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter;
+
+import org.apache.http.client.HttpClient;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver;
+import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver;
+import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ResourceLoader;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Throwables;
+import com.google.common.collect.FluentIterable;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+import net.shibboleth.utilities.java.support.resource.Resource;
+import net.shibboleth.utilities.java.support.xml.ParserPool;
+
+@Slf4j
+public class PvpMetadataResolverFactory implements IDestroyableObject {
+
+ private static final String URI_PREFIX_HTTP = "http:";
+ private static final String URI_PREFIX_HTTPS = "https:";
+
+ private static final String NOT_SUCCESS = "Maybe metadata was expired";
+
+ private Timer timer = null;
+
+ @Autowired
+ private IConfiguration authConfig;
+ @Autowired
+ private ResourceLoader resourceLoader;
+
+ /**
+ * Create a single SAML2 metadata provider by using the default OpenSAML3
+ * parser-pool.
+ *
+ * @param metadataLocation where the metadata should be loaded, but never null.
+ * If the location starts with http(s):, than a http
+ * based metadata provider is used. If the location
+ * starts with file:, than a filesystem based metadata
+ * provider is used
+ * @param filter Filters, which should be used to validate the
+ * metadata
+ * @param idForLogging Id, which is used for Logging
+ * @param httpClient Apache commons 4.x http client
+ *
+ * @return SAML2 Metadata Provider, or null if the metadata provider can not
+ * initialized
+ * @throws Pvp2MetadataException In case of an initialization error
+ */
+ @Nullable
+ public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation,
+ @Nullable final MetadataFilter filter, @Nonnull final String idForLogging,
+ @Nullable final HttpClient httpClient) throws Pvp2MetadataException {
+ return createMetadataProvider(metadataLocation, filter, idForLogging,
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ httpClient);
+
+ }
+
+ /**
+ * Create a single SAML2 metadata provider.
+ *
+ * @param metadataLocation where the metadata should be loaded, but never null.
+ * If the location starts with http(s):, than a http
+ * based metadata provider is used. If the location
+ * starts with file:, than a filesystem based metadata
+ * provider is used
+ * @param filter Filters, which should be used to validate the
+ * metadata
+ * @param idForLogging Id, which is used for Logging
+ * @param httpClient Apache commons 4.x http client
+ *
+ * @return SAML2 Metadata Provider, or null if the metadata provider can not
+ * initialized
+ * @throws Pvp2MetadataException In case of an initialization error
+ */
+ @Nullable
+ public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation,
+ @Nullable final MetadataFilter filter, @Nonnull final String idForLogging,
+ @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) throws Pvp2MetadataException {
+
+ ExtendedRefreshableMetadataResolver internalProvider = null;
+
+ try {
+ if (metadataLocation.startsWith(URI_PREFIX_HTTP)
+ || metadataLocation.startsWith(URI_PREFIX_HTTPS)) {
+ internalProvider = createNewHttpMetaDataProvider(metadataLocation, filter,
+ idForLogging, timer, pool, httpClient);
+
+ } else {
+ final String absoluteMetadataLocation =
+ FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory());
+ final org.springframework.core.io.Resource resource =
+ resourceLoader.getResource(absoluteMetadataLocation);
+
+ if (resource.exists()) {
+ internalProvider = createNewFileSystemMetaDataProvider(
+ new OpenSaml3ResourceAdapter(resource),
+ filter, idForLogging, timer,
+ pool);
+
+ } else {
+ log.warn(
+ "SAML2 metadata file: {} not found or not exist", absoluteMetadataLocation);
+ throw new Pvp2MetadataException("internal.pvp.05",
+ new Object[] { absoluteMetadataLocation, "File NOT found or exist." });
+
+ }
+ }
+
+ } catch (final ComponentInitializationException e) {
+ log.warn("Failed to load Metadata file for {} [ {} ]",
+ idForLogging, e.getMessage());
+ checkResolverInitializationError(e, metadataLocation);
+
+ } catch (final Exception e) {
+ throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() });
+
+ }
+
+ if (!internalProvider.wasLastRefreshSuccess()) {
+ log.info("Metadata loading from source: {} failed. {}", metadataLocation, NOT_SUCCESS);
+ throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, NOT_SUCCESS });
+
+ }
+
+ return new PvpMetadataResolverAdapter(internalProvider);
+
+ }
+
+ @Override
+ public void fullyDestroy() {
+ if (timer != null) {
+ log.info("Stopping timer-thread for PVP metadata resolver ... ");
+ timer.cancel();
+ }
+ }
+
+ @PostConstruct
+ private void initialize() {
+ log.info("Initializing timer-thread for PVP metadata resolver ... ");
+ timer = new Timer("PVP metadata-resolver refresh");
+
+ }
+
+ /**
+ * Create a single SAML2 filesystem based metadata provider.
+ *
+ * @param metadataFile File, where the metadata should be loaded
+ * @param filter Filters, which should be used to validate the metadata
+ * @param idForLogging Id, which is used for Logging
+ * @param timer {@link Timer} which is used to schedule metadata refresh
+ * operations
+ * @param pool SAML2 parser pool that should be used
+ *
+ * @return SAML2 Metadata Provider
+ * @throws IOException In case of a metadata resource error
+ * @throws ComponentInitializationException In case of a metadata resolver
+ * initialization error
+ */
+ private ExtendedRefreshableMetadataResolver createNewFileSystemMetaDataProvider(final Resource metadataFile,
+ final MetadataFilter filter, final String idForLogging, final Timer timer,
+ final ParserPool pool) throws IOException, ComponentInitializationException {
+ ResourceBackedMetadataResolver fileSystemResolver = null;
+ fileSystemResolver = new ResourceBackedMetadataResolver(timer, metadataFile);
+ injectMetadataResolverConfiguration(fileSystemResolver, filter, pool);
+ fileSystemResolver.setId(metadataFile.getURI().toASCIIString());
+ fileSystemResolver.initialize();
+
+ log.trace("Set-up metadata-resolver with ID: {} as: {}",
+ idForLogging, fileSystemResolver.getClass().getSimpleName());
+
+ return fileSystemResolver;
+
+ }
+
+ /**
+ * Create a single SAML2 HTTP metadata provider.
+ *
+ * @param metadataUrl URL, where the metadata should be loaded
+ * @param filter Filters, which should be used to validate the metadata
+ * @param idForLogging Id, which is used for Logging
+ * @param timer {@link Timer} which is used to schedule metadata refresh
+ * operations
+ * @param pool SAML2 parser pool that should be used
+ * @return SAML2 Metadata Provider
+ * @throws ComponentInitializationException In case of a metadata resolver
+ * initialization error
+ * @throws ResolverException In case of an internal OpenSAML
+ * resolver error
+ */
+ private ExtendedRefreshableMetadataResolver createNewHttpMetaDataProvider(final String metadataUrl,
+ final MetadataFilter filter, final String idForLogging, final Timer timer,
+ final ParserPool pool, final HttpClient httpClient) throws ComponentInitializationException,
+ ResolverException {
+ HTTPMetadataResolver httpMetadataResolver = null;
+ httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl);
+ injectMetadataResolverConfiguration(httpMetadataResolver, filter, pool);
+ httpMetadataResolver.setId(metadataUrl);
+ httpMetadataResolver.initialize();
+
+ log.trace("Set-up metadata-resolver with ID: {} as: {}",
+ idForLogging, httpMetadataResolver.getClass().getSimpleName());
+
+ return httpMetadataResolver;
+
+ }
+
+ private void injectMetadataResolverConfiguration(AbstractReloadingMetadataResolver resolver,
+ final MetadataFilter filter, final ParserPool pool) {
+ if (pool != null) {
+ resolver.setParserPool(pool);
+
+ } else {
+ resolver.setParserPool(
+ XMLObjectProviderRegistrySupport.getParserPool());
+
+ }
+
+ resolver.setRequireValidMetadata(true);
+ resolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes
+ resolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours
+ resolver.setMetadataFilter(filter);
+
+ }
+
+ private void checkResolverInitializationError(ComponentInitializationException e, String metadataLocation)
+ throws Pvp2MetadataException {
+ if (FluentIterable.from(Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(SSLHandshakeException.class)).first().isPresent()) {
+ log.info("SSL-Server certificate for metadata: {} not trusted.", metadataLocation, null, e);
+ throw new Pvp2MetadataException("internal.pvp.06", new Object[] { metadataLocation, e.getMessage() },
+ e);
+
+ } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(SignatureValidationException.class)).first().isPresent()) {
+ log.info("Signature verification for metadata: {} FAILED.", metadataLocation, null, e);
+ throw new Pvp2MetadataException("internal.pvp.07", new Object[] { metadataLocation, e.getMessage() },
+ e);
+
+ } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(SchemaValidationException.class)).first().isPresent()) {
+ log.info("Schema validation for metadata: {} FAILED.", metadataLocation, null, e);
+ throw new Pvp2MetadataException("internal.pvp.08", new Object[] { metadataLocation, e.getMessage() },
+ e);
+
+ } else {
+ log.info("Generic initialization error for metadata: {}", metadataLocation, null, e);
+ throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() },
+ e);
+
+ }
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java
deleted file mode 100644
index c16ca5fd..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.metadata;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.util.Timer;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import org.apache.commons.httpclient.HttpClient;
-import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider;
-import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.xml.parse.ParserPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException;
-
-/**
- * @author tlenz
- *
- */
-public abstract class SimpleMetadataProvider implements MetadataProvider{
- private static final Logger log = LoggerFactory.getLogger(SimpleMetadataProvider.class);
-
- private static final String URI_PREFIX_HTTP = "http:";
- private static final String URI_PREFIX_HTTPS = "https:";
- private static final String URI_PREFIX_FILE = "file:";
-
-
- @Autowired
- protected IConfiguration authConfig;
-
-
- /**
- * Create a single SAML2 metadata provider
- *
- * @param metadataLocation where the metadata should be loaded, but never null. If the location starts with http(s):, than a http
- * based metadata provider is used. If the location starts with file:, than a filesystem based metadata provider is used
- * @param filter Filters, which should be used to validate the metadata
- * @param IdForLogging Id, which is used for Logging
- * @param timer {@link Timer} which is used to schedule metadata refresh operations
- * @param httpClient Apache commons 3.x http client
- *
- * @return SAML2 Metadata Provider, or null if the metadata provider can not initialized
- */
- protected MetadataProvider createNewSimpleMetadataProvider(String metadataLocation, MetadataFilter filter,
- String IdForLogging, Timer timer, ParserPool pool, HttpClient httpClient) {
- if (metadataLocation.startsWith(URI_PREFIX_HTTP) || metadataLocation.startsWith(URI_PREFIX_HTTPS)) {
- if (httpClient != null)
- return createNewHTTPMetaDataProvider(metadataLocation, filter, IdForLogging, timer, pool, httpClient);
-
- else {
- log.warn("Can not load http(s) based SAML2 metadata without a HTTP client");
- return null;
- }
-
- } else {
- String absoluteMetadataLocation;
- try {
- absoluteMetadataLocation = FileUtils.makeAbsoluteURL(
- metadataLocation,
- authConfig.getConfigurationRootDirectory());
-
- if (absoluteMetadataLocation.startsWith(URI_PREFIX_FILE)) {
- File metadataFile = new File(absoluteMetadataLocation);
- if (metadataFile.exists())
- return createNewFileSystemMetaDataProvider(metadataFile, filter, IdForLogging, timer, pool);
-
- else {
- log.warn("SAML2 metadata file: " + absoluteMetadataLocation + " not found or not exist");
- return null;
- }
-
- }
-
-
- } catch (MalformedURLException e) {
- log.warn("SAML2 metadata URL is invalid: " + metadataLocation, e);
-
- }
-
- }
-
- log.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation);
- return null;
-
- }
-
-
- /**
- * Create a single SAML2 filesystem based metadata provider
- *
- * @param metadataFile File, where the metadata should be loaded
- * @param filter Filters, which should be used to validate the metadata
- * @param IdForLogging Id, which is used for Logging
- * @param timer {@link Timer} which is used to schedule metadata refresh operations
- * @param pool
- *
- * @return SAML2 Metadata Provider
- */
- private MetadataProvider createNewFileSystemMetaDataProvider(File metadataFile, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool) {
- FilesystemMetadataProvider fileSystemProvider = null;
- try {
- fileSystemProvider = new FilesystemMetadataProvider(timer, metadataFile);
- fileSystemProvider.setParserPool(pool);
- fileSystemProvider.setRequireValidMetadata(true);
- fileSystemProvider.setMinRefreshDelay(1000*60*15); //15 minutes
- fileSystemProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours
- //httpProvider.setRefreshDelayFactor(0.1F);
-
- fileSystemProvider.setMetadataFilter(filter);
- fileSystemProvider.initialize();
-
- fileSystemProvider.setRequireValidMetadata(true);
-
- return fileSystemProvider;
-
- } catch (Exception e) {
- log.warn(
- "Failed to load Metadata file for "
- + IdForLogging + "[ "
- + "File: " + metadataFile.getAbsolutePath()
- + " Msg: " + e.getMessage() + " ]", e);
-
-
- log.warn("Can not initialize SAML2 metadata provider from filesystem: " + metadataFile.getAbsolutePath()
- + " Reason: " + e.getMessage(), e);
-
- if (fileSystemProvider != null)
- fileSystemProvider.destroy();
-
- }
-
- return null;
-
- }
-
-
-
- /**
- * Create a single SAML2 HTTP metadata provider
- *
- * @param metadataURL URL, where the metadata should be loaded
- * @param filter Filters, which should be used to validate the metadata
- * @param IdForLogging Id, which is used for Logging
- * @param timer {@link Timer} which is used to schedule metadata refresh operations
- * @param pool
- *
- * @return SAML2 Metadata Provider
- */
- private MetadataProvider createNewHTTPMetaDataProvider(String metadataURL, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool, HttpClient httpClient) {
- HTTPMetadataProvider httpProvider = null;
- try {
- httpProvider = new HTTPMetadataProvider(timer, httpClient,
- metadataURL);
- httpProvider.setParserPool(pool);
- httpProvider.setRequireValidMetadata(true);
- httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes
- httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours
- //httpProvider.setRefreshDelayFactor(0.1F);
-
- httpProvider.setMetadataFilter(filter);
- httpProvider.initialize();
-
- httpProvider.setRequireValidMetadata(true);
-
- return httpProvider;
-
- } catch (Throwable e) {
- if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) {
- log.warn("SSL-Server certificate for metadata "
- + metadataURL + " not trusted.", e);
-
- } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) {
- log.warn("Signature verification for metadata"
- + metadataURL + " FAILED.", e);
-
- } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) {
- log.warn("Schema validation for metadata "
- + metadataURL + " FAILED.", e);
- }
-
- log.warn(
- "Failed to load Metadata file for "
- + IdForLogging + "[ "
- + e.getMessage() + " ]", e);
-
- if (httpProvider != null) {
- log.debug("Destroy failed Metadata provider");
- httpProvider.destroy();
- }
-
-// if (timer != null) {
-// log.debug("Destroy Timer.");
-// timer.cancel();
-// }
-
-
- }
-
- return null;
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
new file mode 100644
index 00000000..fdd44b9a
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java
@@ -0,0 +1,79 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+
+/**
+ * SAML2 Post-Binding decoder with same EAAF specific hardening regarding http
+ * request-parameter processing.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafHttpPostDecoder extends HTTPPostDecoder {
+
+ private static final String SAML_REQ_PARAM_NAME = "SAMLRequest";
+ private static final String SAML_RESP_PARAM_NAME = "SAMLResponse";
+
+ public EaafHttpPostDecoder(HttpServletRequest req) {
+ setHttpServletRequest(req);
+ }
+
+ @Override
+ protected InputStream getBase64DecodedMessage(final HttpServletRequest request)
+ throws MessageDecodingException {
+
+ log.debug("Getting Base64 encoded message from request");
+ String encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME);
+ if (Strings.isNullOrEmpty(encodedMessage)) {
+ encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME);
+
+ }
+
+ if (Strings.isNullOrEmpty(encodedMessage)) {
+ log.info("Request did not contain either a SAMLRequest or "
+ + "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding.");
+ throw new MessageDecodingException("No SAML message present in request");
+ }
+
+ log.trace("Base64 decoding SAML message: {}", encodedMessage);
+ final byte[] decodedBytes = Base64Support.decode(encodedMessage);
+
+ try {
+ log.trace("Decoded SAML message: {}", new String(decodedBytes, "UTF-8"));
+
+ } catch (final UnsupportedEncodingException e) {
+ log.warn("Logging of incomming message failed", e);
+
+ }
+
+ return new ByteArrayInputStream(decodedBytes);
+ }
+
+ /**
+ * EAAF specific unmarshaller perform XML schema validation before unmarshalling
+ * the SAML message.
+ *
+ */
+ @Override
+ protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {
+ return Saml2Utils.unmarshallMessage(messageStream);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
new file mode 100644
index 00000000..c5174f02
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java
@@ -0,0 +1,97 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * SAML2 Redirect-Binding deflate decoder with same EAAF specific hardening
+ * regarding http request-parameter processing.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder {
+
+ private static final String SAML_REQ_PARAM_NAME = "SAMLRequest";
+ private static final String SAML_RESP_PARAM_NAME = "SAMLResponse";
+
+ public EaafHttpRedirectDeflateDecoder(HttpServletRequest req) {
+ setHttpServletRequest(req);
+
+ }
+
+ @Override
+ protected void doDecode() throws MessageDecodingException {
+ final MessageContext<SAMLObject> messageContext = new MessageContext<>();
+ final HttpServletRequest request = getHttpServletRequest();
+
+ if (!"GET".equalsIgnoreCase(request.getMethod())) {
+ throw new MessageDecodingException("This message decoder only supports the HTTP GET method");
+ }
+
+ final String samlEncoding = StringSupport.trimOrNull(request.getParameter("SAMLEncoding"));
+ if (samlEncoding != null && !SAMLConstants.SAML2_BINDING_URL_ENCODING_DEFLATE_URI.equals(samlEncoding)) {
+ throw new MessageDecodingException("Request indicated an unsupported SAMLEncoding: " + samlEncoding);
+
+ }
+
+ final String relayState = request.getParameter("RelayState");
+ log.debug("Decoded RelayState: {}", relayState);
+ SAMLBindingSupport.setRelayState(messageContext, relayState);
+
+ final InputStream samlMessageIns;
+
+ // implement parameter extraction as same as in
+ // SAML2HTTPRedirectDeflateSignatureSecurityHandler.java
+ final String samlReq = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME);
+ final String samlResp = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME);
+ if (!Strings.isNullOrEmpty(samlReq)) {
+ samlMessageIns = decodeMessage(samlReq);
+
+ } else if (!Strings.isNullOrEmpty(samlResp)) {
+ samlMessageIns = decodeMessage(samlResp);
+
+ } else {
+ throw new MessageDecodingException(
+ "No SAMLRequest or SAMLResponse query path parameter, invalid SAML 2 HTTP Redirect message");
+ }
+
+ final SAMLObject samlMessage = (SAMLObject) unmarshallMessage(samlMessageIns);
+ messageContext.setMessage(samlMessage);
+ log.debug("Decoded SAML message");
+
+ populateBindingContext(messageContext);
+
+ setMessageContext(messageContext);
+
+ }
+
+ /**
+ * EAAF specific unmarshaller perform XML schema validation before unmarshalling
+ * the SAML message.
+ *
+ */
+ @Override
+ protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {
+ return Saml2Utils.unmarshallMessage(messageStream);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java
new file mode 100644
index 00000000..1611d623
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.security.KeyStore;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.security.x509.impl.KeyStoreX509CredentialAdapter;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * OpenSAML2 KeyStore adapter.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAdapter
+ implements EaafX509Credential {
+
+ private String signatureAlgorithmtToUse;
+ private String keyEncryptionAlgorithmtToUse;
+
+ /**
+ * Get an OpenSAML2 keystore.
+ *
+ * @param store Java KeyStore
+ * @param alias Key alias
+ * @param password key Password
+ * @param keyStoreFriendlyName Friendlyname of this keystore for logging
+ * purposes
+ * @throws CredentialsNotAvailableException In case of an initialization
+ * exception
+ */
+ public EaafKeyStoreX509CredentialAdapter(@Nonnull final KeyStore store, @Nonnull final String alias,
+ @Nullable final char[] password, @Nonnull String keyStoreFriendlyName)
+ throws CredentialsNotAvailableException {
+ super(store, alias, password);
+
+ if (getPrivateKey() == null && getSecretKey() == null) {
+ log.error("KeyStore: {} Key with alias: {} not found or contains no PrivateKey.",
+ keyStoreFriendlyName, alias);
+ throw new CredentialsNotAvailableException("internal.pvp.00",
+ new Object[] { keyStoreFriendlyName, alias });
+
+ }
+
+ try {
+ setSignatureAlgorithmForSigning(Saml2Utils.getKeyOperationAlgorithmFromCredential(this,
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC));
+
+ setKeyEncryptionAlgorithmForDataEncryption(
+ Saml2Utils.getKeyOperationAlgorithmFromCredential(this,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC));
+
+ } catch (final SamlSigningException e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] { keyStoreFriendlyName,
+ alias }, e);
+
+ }
+
+ }
+
+ @Override
+ public Class<? extends X509Credential> getCredentialType() {
+ return X509Credential.class;
+ }
+
+ @Override
+ public String getSignatureAlgorithmForSigning() {
+ return this.signatureAlgorithmtToUse;
+
+ }
+
+ @Override
+ public void setSignatureAlgorithmForSigning(String sigAlg) {
+ this.signatureAlgorithmtToUse = sigAlg;
+
+ }
+
+ @Override
+ public String getKeyEncryptionAlgorithmForDataEncryption() {
+ return this.keyEncryptionAlgorithmtToUse;
+
+ }
+
+ @Override
+ public void setKeyEncryptionAlgorithmForDataEncryption(String sigAlg) {
+ this.keyEncryptionAlgorithmtToUse = sigAlg;
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java
deleted file mode 100644
index 8af12acc..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.VelocityEngine;
-import org.opensaml.common.binding.SAMLMessageContext;
-import org.opensaml.saml2.binding.encoding.HTTPPostEncoder;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.transport.http.HTTPOutTransport;
-import org.opensaml.ws.transport.http.HTTPTransportUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import at.gv.egiz.eaaf.core.api.gui.IVelocityGUIBuilderConfiguration;
-import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;
-
-/**
- * @author tlenz
- *
- */
-public class HTTPPostEncoderWithOwnTemplate extends HTTPPostEncoder {
- private static final Logger log = LoggerFactory.getLogger(HTTPPostEncoderWithOwnTemplate.class);
-
-
- private final VelocityEngine velocityEngine;
- private final IVelocityGUIBuilderConfiguration guiConfig;
- private final IVelocityGuiFormBuilder guiBuilder;
-
- /**
- * @param engine
- * @param templateId
- */
- public HTTPPostEncoderWithOwnTemplate(IVelocityGUIBuilderConfiguration guiConfig, IVelocityGuiFormBuilder guiBuilder, VelocityEngine engine) {
- super(engine, null);
- this.velocityEngine = engine;
- this.guiConfig = guiConfig;
- this.guiBuilder = guiBuilder;
-
- }
-
- /**
- * Base64 and POST encodes the outbound message and writes it to the outbound transport.
- *
- * @param messageContext current message context
- * @param endpointURL endpoint URL to which to encode message
- *
- * @throws MessageEncodingException thrown if there is a problem encoding the message
- */
- @Override
- protected void postEncode(SAMLMessageContext messageContext, String endpointURL) throws MessageEncodingException {
- log.debug("Invoking Velocity template to create POST body");
- InputStream is = null;
- try {
- //build Velocity Context from GUI input paramters
- final VelocityContext context = guiBuilder.generateVelocityContextFromConfiguration(guiConfig);
-
- //load template
- is = guiBuilder.getTemplateInputStream(guiConfig);
-
- //populate velocity context with SAML2 parameters
- populateVelocityContext(context, messageContext, endpointURL);
-
- //populate transport parameter
- final HTTPOutTransport outTransport = (HTTPOutTransport) messageContext.getOutboundMessageTransport();
- HTTPTransportUtils.addNoCacheHeaders(outTransport);
- HTTPTransportUtils.setUTF8Encoding(outTransport);
- HTTPTransportUtils.setContentType(outTransport, "text/html");
-
- //evaluate template and write content to response
- final Writer out = new OutputStreamWriter(outTransport.getOutgoingStream(), "UTF-8");
- velocityEngine.evaluate(context, out, "SAML2_POST_BINDING", new BufferedReader(new InputStreamReader(is)));
- out.flush();
-
- } catch (final Exception e) {
- log.error("Error invoking Velocity template", e);
- throw new MessageEncodingException("Error creating output document", e);
-
- } finally {
- if (is != null) {
- try {
- is.close();
-
- } catch (final IOException e) {
- log.error("Can NOT close GUI-Template InputStream.", e);
- }
- }
-
- }
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java
new file mode 100644
index 00000000..fa77b73c
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;
+import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPPostEncoder;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.net.HttpServletSupport;
+
+/**
+ * OpenSAML2 Post-Binding encoder that uses dynamic loaded templates.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {
+
+ private final IVelocityGuiBuilderConfiguration guiConfig;
+ private final IVelocityGuiFormBuilder guiBuilder;
+
+ /**
+ * Own Post-Binding encoder.
+ *
+ * @param guiConfig GUI configuration
+ * @param guiBuilder GUI builder implementation
+ * @throws Exception In case of a {@link Velocity} initialization error
+ */
+ public HttpPostEncoderWithOwnTemplate(final IVelocityGuiBuilderConfiguration guiConfig,
+ final IVelocityGuiFormBuilder guiBuilder) throws Exception {
+ this.guiConfig = guiConfig;
+ this.guiBuilder = guiBuilder;
+
+ setVelocityEngine(VelocityProvider.getClassPathVelocityEngine());
+
+ }
+
+ /**
+ * Base64 and POST encodes the out-bound message and writes it to the out-bound
+ * transport.
+ *
+ * @param messageContext current message context
+ *
+ * @throws MessageEncodingException thrown if there is a problem encoding the
+ * message
+ */
+ @Override
+ protected void postEncode(final MessageContext<SAMLObject> messageContext, final String endpointUrl)
+ throws MessageEncodingException {
+ log.debug("Invoking Velocity template to create POST body");
+ InputStream is = null;
+ try {
+ // build Velocity Context from GUI input paramters
+ final VelocityContext context =
+ guiBuilder.generateVelocityContextFromConfiguration(guiConfig);
+
+ // load template
+ is = guiBuilder.getTemplateInputStream(guiConfig);
+
+ populateVelocityContext(context, messageContext, endpointUrl);
+
+ final HttpServletResponse response = getHttpServletResponse();
+
+ HttpServletSupport.addNoCacheHeaders(response);
+ HttpServletSupport.setUTF8Encoding(response);
+ HttpServletSupport.setContentType(response, "text/html");
+
+ final Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
+ getVelocityEngine().evaluate(context, out, "SAML2_POST_BINDING",
+ new BufferedReader(new InputStreamReader(is, "UTF-8")));
+ out.flush();
+
+ } catch (final Exception e) {
+ log.error("Error invoking Velocity template", e);
+ throw new MessageEncodingException("Error creating output document", e);
+
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+
+ } catch (final IOException e) {
+ log.error("Can NOT close GUI-Template InputStream.", e);
+ }
+ }
+
+ }
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java
deleted file mode 100644
index 2f3912ca..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
-
-import java.security.KeyStore;
-
-import org.opensaml.xml.security.x509.X509Credential;
-
-
-/**
- * @author tlenz
- *
- */
-public class KeyStoreX509CredentialAdapter extends
- org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter {
-
- /**
- * @param store
- * @param alias
- * @param password
- */
- public KeyStoreX509CredentialAdapter(KeyStore store, String alias,
- char[] password) {
- super(store, alias, password);
- }
-
- public Class<? extends X509Credential> getCredentialType() {
- return X509Credential.class;
- }
-
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java
new file mode 100644
index 00000000..f474267f
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java
@@ -0,0 +1,86 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+import net.shibboleth.utilities.java.support.resource.Resource;
+
+/**
+ * Adapter that connects a Spring {@link org.springframework.core.io.Resource}
+ * to a {@link Resource}.
+ *
+ * @author tlenz
+ *
+ */
+public class OpenSaml3ResourceAdapter implements Resource {
+
+ private final org.springframework.core.io.Resource internalResource;
+
+ public OpenSaml3ResourceAdapter(org.springframework.core.io.Resource resource) {
+ this.internalResource = resource;
+ }
+
+ @Override
+ public boolean exists() {
+ return internalResource.exists();
+ }
+
+ @Override
+ public boolean isReadable() {
+ return internalResource.isReadable();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return internalResource.isOpen();
+ }
+
+ @Override
+ public URL getURL() throws IOException {
+ return internalResource.getURL();
+ }
+
+ @Override
+ public URI getURI() throws IOException {
+ return internalResource.getURI();
+ }
+
+ @Override
+ public File getFile() throws IOException {
+ return internalResource.getFile();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return internalResource.getInputStream();
+ }
+
+ @Override
+ public long contentLength() throws IOException {
+ return internalResource.contentLength();
+ }
+
+ @Override
+ public long lastModified() throws IOException {
+ return internalResource.lastModified();
+ }
+
+ @Override
+ public Resource createRelativeResource(String relativePath) throws IOException {
+ throw new IOException("This method is not supperted by this adapter");
+ }
+
+ @Override
+ public String getFilename() {
+ return internalResource.getFilename();
+ }
+
+ @Override
+ public String getDescription() {
+ return internalResource.getDescription();
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java
index 544dc9f5..38735fb8 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java
@@ -1,81 +1,66 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;
-import org.opensaml.common.binding.SAMLMessageContext;
-import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
-import org.opensaml.ws.message.MessageContext;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap;
+import lombok.extern.slf4j.Slf4j;
/**
+ * Create deflate encoded SAML2 redirect-binding informations.
+ *
* @author tlenz
*
*/
+
+@Slf4j
public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {
- private static final Logger log = LoggerFactory.getLogger(StringRedirectDeflateEncoder.class);
-
- private String redirectURL = null;
-
- public void encode(MessageContext messageContext)
- throws MessageEncodingException {
- if (!(messageContext instanceof SAMLMessageContext)) {
- log.error("Invalid message context type, this encoder only support SAMLMessageContext");
- throw new MessageEncodingException(
- "Invalid message context type, this encoder only support SAMLMessageContext");
- }
+ private String redirectUrl = null;
+
+ @Override
+ protected void doEncode() throws MessageEncodingException {
+ final MessageContext<SAMLObject> messageContext = getMessageContext();
+ final SAMLObject outboundMessage = messageContext.getMessage();
+
+ final String endpointUrl = getEndpointURL(messageContext).toString();
- //load default PVP security configurations
- EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration();
-
- SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
+ removeSignature(outboundMessage);
- String endpointURL = getEndpointURL(samlMsgCtx).buildURL();
+ final String encodedMessage = deflateAndBase64Encode(outboundMessage);
- setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointURL);
+ redirectUrl = buildRedirectURL(messageContext, endpointUrl, encodedMessage);
- removeSignature(samlMsgCtx);
+ log.trace("SAML2 redirect-binding URL was generated as: {}", redirectUrl);
- String encodedMessage = deflateAndBase64Encode(samlMsgCtx
- .getOutboundSAMLMessage());
+ }
- redirectURL = buildRedirectURL(samlMsgCtx, endpointURL,
- encodedMessage);
- }
+ /**
+ * Get generated redirect URL.
+ *
+ * @return the redirectURL
+ */
+ public String getRedirectUrl() {
+ return redirectUrl;
+ }
- /**
- * @return the redirectURL
- */
- public String getRedirectURL() {
- return redirectURL;
- }
-
-
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java
deleted file mode 100644
index 266b6e5f..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
-
-import org.opensaml.Configuration;
-import org.opensaml.DefaultBootstrap;
-import org.opensaml.xml.ConfigurationException;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeMarshaller;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeUnmarshaller;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesMarshaller;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesUnmarshaller;
-
-/**
- * @author tlenz
- *
- */
-public class EAAFDefaultSAML2Bootstrap extends DefaultBootstrap {
-
- public static synchronized void bootstrap() throws ConfigurationException {
-
- initializeXMLSecurity();
-
- initializeXMLTooling();
-
- initializeArtifactBuilderFactories();
-
- initializeGlobalSecurityConfiguration();
-
- initializeParserPool();
-
- initializeESAPI();
-
- initializeExtenstions();
-
- }
-
- private static void initializeExtenstions() {
- Configuration.registerObjectProvider(
- EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME,
- new EAAFRequestedAttributeBuilder(),
- new EAAFRequestedAttributeMarshaller(),
- new EAAFRequestedAttributeUnmarshaller()
- );
-
- Configuration.registerObjectProvider(
- EAAFRequestedAttributes.DEFAULT_ELEMENT_NAME,
- new EAAFRequestedAttributesBuilder(),
- new EAAFRequestedAttributesMarshaller(),
- new EAAFRequestedAttributesUnmarshaller()
- );
-
- }
-
- public static void initializeDefaultPVPConfiguration() {
- initializeGlobalSecurityConfiguration();
-
- }
-
- /**
- * Initializes the default global security configuration.
- */
- protected static void initializeGlobalSecurityConfiguration() {
- Configuration.setGlobalSecurityConfiguration(EAAFDefaultSecurityConfigurationBootstrap.buildDefaultConfig());
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java
deleted file mode 100644
index ddd5b13e..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
-
-import org.opensaml.xml.encryption.EncryptionConstants;
-import org.opensaml.xml.security.BasicSecurityConfiguration;
-import org.opensaml.xml.security.DefaultSecurityConfigurationBootstrap;
-import org.opensaml.xml.security.credential.BasicKeyInfoGeneratorFactory;
-import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorManager;
-import org.opensaml.xml.security.keyinfo.NamedKeyInfoGeneratorManager;
-import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory;
-import org.opensaml.xml.signature.SignatureConstants;
-
-/**
- * @author tlenz
- *
- */
-public class EAAFDefaultSecurityConfigurationBootstrap extends
- DefaultSecurityConfigurationBootstrap {
-
- public static BasicSecurityConfiguration buildDefaultConfig() {
- BasicSecurityConfiguration config = new BasicSecurityConfiguration();
-
- populateSignatureParams(config);
- populateEncryptionParams(config);
- populateKeyInfoCredentialResolverParams(config);
- populateKeyInfoGeneratorManager(config);
- populateKeyParams(config);
-
- return config;
- }
-
- protected static void populateKeyInfoGeneratorManager(
- BasicSecurityConfiguration config) {
- NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager();
- config.setKeyInfoGeneratorManager(namedManager);
-
- namedManager.setUseDefaultManager(true);
- KeyInfoGeneratorManager defaultManager = namedManager
- .getDefaultManager();
-
- BasicKeyInfoGeneratorFactory basicFactory = new BasicKeyInfoGeneratorFactory();
- basicFactory.setEmitPublicKeyValue(true);
-
- X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory();
- x509Factory.setEmitEntityCertificate(true);
-
- defaultManager.registerFactory(basicFactory);
- defaultManager.registerFactory(x509Factory);
- }
-
- protected static void populateSignatureParams(
- BasicSecurityConfiguration config) {
-
- //use SHA256 instead of SHA1
- config.registerSignatureAlgorithmURI("RSA",
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
-
- config.registerSignatureAlgorithmURI("DSA",
- "http://www.w3.org/2000/09/xmldsig#dsa-sha1");
-
- //use SHA256 instead of SHA1
- config.registerSignatureAlgorithmURI("EC",
- SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256);
-
- //use SHA256 instead of SHA1
- config.registerSignatureAlgorithmURI("AES",
- SignatureConstants.ALGO_ID_MAC_HMAC_SHA256);
-
-
- config.registerSignatureAlgorithmURI("DESede",
- SignatureConstants.ALGO_ID_MAC_HMAC_SHA256);
-
- config.setSignatureCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#");
- config.setSignatureHMACOutputLength(null);
-
- //use SHA256 instead of SHA1
- config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
- }
-
- protected static void populateEncryptionParams(
- BasicSecurityConfiguration config) {
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128),
- "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192),
- "http://www.w3.org/2001/04/xmlenc#aes192-cbc");
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256),
- "http://www.w3.org/2001/04/xmlenc#aes256-cbc");
-
- //support GCM mode
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128),
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM);
-
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192),
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM);
-
- config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256),
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM);
-
-
- config.registerDataEncryptionAlgorithmURI("DESede",
- Integer.valueOf(168),
- "http://www.w3.org/2001/04/xmlenc#tripledes-cbc");
- config.registerDataEncryptionAlgorithmURI("DESede",
- Integer.valueOf(192),
- "http://www.w3.org/2001/04/xmlenc#tripledes-cbc");
-
- config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, "AES",
- "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
-
- config.registerKeyTransportEncryptionAlgorithmURI("RSA", null,
- "DESede", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
-
- config.registerKeyTransportEncryptionAlgorithmURI("AES",
- Integer.valueOf(128), null,
- "http://www.w3.org/2001/04/xmlenc#kw-aes128");
- config.registerKeyTransportEncryptionAlgorithmURI("AES",
- Integer.valueOf(192), null,
- "http://www.w3.org/2001/04/xmlenc#kw-aes192");
- config.registerKeyTransportEncryptionAlgorithmURI("AES",
- Integer.valueOf(256), null,
- "http://www.w3.org/2001/04/xmlenc#kw-aes256");
- config.registerKeyTransportEncryptionAlgorithmURI("DESede",
- Integer.valueOf(168), null,
- "http://www.w3.org/2001/04/xmlenc#kw-tripledes");
- config.registerKeyTransportEncryptionAlgorithmURI("DESede",
- Integer.valueOf(192), null,
- "http://www.w3.org/2001/04/xmlenc#kw-tripledes");
-
- config.setAutoGeneratedDataEncryptionKeyAlgorithmURI("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java
new file mode 100644
index 00000000..97f0f225
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+import org.opensaml.xmlsec.encryption.support.RSAOAEPParameters;
+import org.opensaml.xmlsec.impl.BasicDecryptionConfiguration;
+import org.opensaml.xmlsec.impl.BasicEncryptionConfiguration;
+import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
+import org.opensaml.xmlsec.impl.BasicSignatureValidationConfiguration;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+
+/**
+ * EAAF specific OpenSAML2 security configuration.
+ *
+ * @author tlenz
+ *
+ */
+public class EaafDefaultSecurityConfigurationBootstrap
+ extends DefaultSecurityConfigurationBootstrap {
+
+ /**
+ * Set EAAF specific encryption configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicEncryptionConfiguration buildEaafEncryptionConfiguration() {
+ final BasicEncryptionConfiguration config = new BasicEncryptionConfiguration();
+
+ config.setBlacklistedAlgorithms(Arrays.asList(
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES,
+ EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES));
+
+ config.setDataEncryptionAlgorithms(Arrays.asList(
+ // The order of these is significant.
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256,
+
+ // register GCM algorithms
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM,
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM));
+
+ config.setKeyTransportEncryptionAlgorithms(Arrays.asList(
+ // The order of the RSA algos is significant.
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP,
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11,
+
+ // The order of these is not significant.
+ // These aren't really "preferences" per se. They just need to be registered
+ // so that they can be used if a credential with a key of that type and size is
+ // seen.
+ EncryptionConstants.ALGO_ID_KEYWRAP_AES128,
+ EncryptionConstants.ALGO_ID_KEYWRAP_AES192,
+ EncryptionConstants.ALGO_ID_KEYWRAP_AES256));
+
+ config.setRSAOAEPParameters(new RSAOAEPParameters(
+ SignatureConstants.ALGO_ID_DIGEST_SHA1,
+ EncryptionConstants.ALGO_ID_MGF1_SHA1,
+ null));
+
+ config.setDataKeyInfoGeneratorManager(buildDataEncryptionKeyInfoGeneratorManager());
+ config.setKeyTransportKeyInfoGeneratorManager(buildKeyTransportEncryptionKeyInfoGeneratorManager());
+
+ return config;
+ }
+
+ /**
+ * Set EAAF specific decryption configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicDecryptionConfiguration buildEaaftDecryptionConfiguration() {
+ final BasicDecryptionConfiguration config = new BasicDecryptionConfiguration();
+
+ config.setBlacklistedAlgorithms(Collections.singletonList(
+ EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15));
+
+ config.setEncryptedKeyResolver(buildBasicEncryptedKeyResolver());
+
+ return config;
+ }
+
+ /**
+ * Set EAAF specific signature-creation configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicSignatureSigningConfiguration buildEaafSignatureSigningConfiguration() {
+ final BasicSignatureSigningConfiguration config = new BasicSignatureSigningConfiguration();
+
+ config.setBlacklistedAlgorithms(Arrays.asList(
+ SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5,
+ SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1,
+ SignatureConstants.ALGO_ID_DIGEST_SHA1));
+
+ config.setSignatureAlgorithms(Arrays.asList(
+ // The order within each key group is significant.
+ // The order of the key groups themselves is not significant.
+
+ // RSA
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512,
+
+ // ECDSA
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512
+
+ // HMAC (all symmetric keys)
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA256,
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA384,
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA512,
+ // SignatureConstants.ALGO_ID_MAC_HMAC_SHA1
+ ));
+
+ config.setSignatureReferenceDigestMethods(Arrays.asList(
+ // The order of these is significant.
+ SignatureConstants.ALGO_ID_DIGEST_SHA256,
+ SignatureConstants.ALGO_ID_DIGEST_SHA384,
+ SignatureConstants.ALGO_ID_DIGEST_SHA512));
+
+ config.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+
+ config.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());
+
+ return config;
+ }
+
+ /**
+ * Set EAAF specific signature-verification configuration to OpenSAML 3.x.
+ *
+ * @return
+ */
+ public static BasicSignatureValidationConfiguration buildEaafSignatureValidationConfiguration() {
+ final BasicSignatureValidationConfiguration config = new BasicSignatureValidationConfiguration();
+
+ config.setBlacklistedAlgorithms(Arrays.asList(
+ SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5,
+ SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5,
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1,
+ SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1,
+ SignatureConstants.ALGO_ID_DIGEST_SHA1));
+
+ return config;
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java
new file mode 100644
index 00000000..5c6d861d
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.xml.XMLConstants;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeMarshaller;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeUnmarshaller;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesMarshaller;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesUnmarshaller;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.config.InitializationException;
+import org.opensaml.core.config.InitializationService;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.xmlsec.DecryptionConfiguration;
+import org.opensaml.xmlsec.EncryptionConfiguration;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.xml.BasicParserPool;
+import net.shibboleth.utilities.java.support.xml.ParserPool;
+
+/**
+ * EAAF specific OpenSAML Initializer.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafOpenSaml3xInitializer extends InitializationService {
+
+ /**
+ * EAAF specific OpenSAML3.x initialization.
+ *
+ * @throws InitializationException In case of an error
+ * @throws ComponentInitializationException In case of an OpenSAML3
+ * initialization error
+ */
+ public static synchronized void eaafInitialize() throws InitializationException,
+ ComponentInitializationException {
+ log.debug("Initializing OpenSAML 3.x ... ");
+ initialize();
+
+ log.debug("Injecting EAAF-specific configuration into OpenSAML 3.x ... ");
+ injectEaafSecurityProperty();
+ injectEaafExtenstions();
+
+ XMLObjectProviderRegistrySupport.setParserPool(eaafSecuredBasicParserPool());
+
+ log.info("OpenSAML3.x with EAAF extensions initialized");
+
+ }
+
+ private static void injectEaafSecurityProperty() {
+ ConfigurationService.register(EncryptionConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaafEncryptionConfiguration());
+
+ ConfigurationService.register(DecryptionConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaaftDecryptionConfiguration());
+
+ ConfigurationService.register(SignatureSigningConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureSigningConfiguration());
+
+ ConfigurationService.register(SignatureValidationConfiguration.class,
+ EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureValidationConfiguration());
+
+ }
+
+ private static void injectEaafExtenstions() {
+ XMLObjectProviderRegistrySupport.registerObjectProvider(
+ EaafRequestedAttribute.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributeBuilder(),
+ new EaafRequestedAttributeMarshaller(), new EaafRequestedAttributeUnmarshaller());
+
+ XMLObjectProviderRegistrySupport.registerObjectProvider(
+ EaafRequestedAttributes.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributesBuilder(),
+ new EaafRequestedAttributesMarshaller(), new EaafRequestedAttributesUnmarshaller());
+
+ }
+
+ /**
+ * Build a secured OpenSAML 3.x XML parser-pool.
+ *
+ * @return {@link ParserPool}
+ * @throws ComponentInitializationException In case of an initialization error
+ */
+ @Nonnull
+ private static ParserPool eaafSecuredBasicParserPool() throws ComponentInitializationException {
+ // Get parser pool manager
+ final BasicParserPool ppMgr = new BasicParserPool();
+ // Note: this is necessary due to an unresolved Xerces deferred DOM issue/bug
+ ppMgr.setBuilderFeatures(getSecureDocumentBuilderFeatures());
+ ppMgr.setNamespaceAware(true);
+ ppMgr.setIgnoreComments(true);
+ ppMgr.setExpandEntityReferences(false);
+ ppMgr.setXincludeAware(false);
+ ppMgr.initialize();
+ return ppMgr;
+ }
+
+ @Nonnull
+ private static Map<String, Boolean> getSecureDocumentBuilderFeatures() {
+ final Map<String, Boolean> features = new HashMap<>();
+ features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+
+ // Ignore the external DTD completely
+ // Note: this is for Xerces only:
+ features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", Boolean.FALSE);
+ // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all
+ // XML entity attacks are prevented
+ // Xerces 2 only -
+ // http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
+ features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE);
+
+ // If you can't completely disable DTDs, then at least do the following:
+ // Xerces 1 -
+ // http://xerces.apache.org/xerces-j/features.html#external-general-entities
+ // Xerces 2 -
+ // http://xerces.apache.org/xerces2-j/features.html#external-general-entities
+ features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE);
+
+ // Xerces 1 -
+ // http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
+ // Xerces 2 -
+ // http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
+ features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE);
+
+ return features;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java
deleted file mode 100644
index ed169d8c..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.reqattr;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.opensaml.common.impl.AbstractSAMLObject;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.schema.XSBooleanValue;
-import org.opensaml.xml.util.AttributeMap;
-import org.opensaml.xml.util.XMLObjectChildrenList;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-
-public class EAAFRequestedAttributeImpl extends AbstractSAMLObject implements EAAFRequestedAttribute {
-
- private final XMLObjectChildrenList<XMLObject> attributeValues;
- private String friendlyName;
- private String isRequired;
- private String name;
- private String nameFormat;
- private AttributeMap unknownAttributes;
-
- public EAAFRequestedAttributeImpl(String namespaceURI, String elementLocalName, String namespacePrefix) {
- super(namespaceURI, elementLocalName, namespacePrefix);
- unknownAttributes = new AttributeMap(this);
- attributeValues = new XMLObjectChildrenList<XMLObject>(this);
-
- }
-
- public final List<XMLObject> getAttributeValues() {
- return attributeValues;
- }
-
- public final String getFriendlyName() {
- return friendlyName;
- }
-
- public final String getIsRequiredXSBoolean() {
- return isRequired;
- }
-
- public final String getName() {
- return name;
- }
-
- public final String getNameFormat() {
- return nameFormat;
- }
-
- public final List<XMLObject> getOrderedChildren() {
- final List<XMLObject> children = new ArrayList<XMLObject>();
- children.addAll(attributeValues);
- return Collections.unmodifiableList(children);
- }
-
-
- public final AttributeMap getUnknownAttributes() {
- return unknownAttributes;
- }
-
-
- public final void setFriendlyName(final String newFriendlyName) {
- this.friendlyName = prepareForAssignment(this.friendlyName,
- newFriendlyName);
- }
-
-
- public final void setIsRequired(final String newIsRequired) {
- isRequired = prepareForAssignment(this.isRequired, newIsRequired);
-
- }
-
-
- public final void setName(final String newName) {
- this.name = prepareForAssignment(this.name, newName);
- }
-
-
- public final void setNameFormat(final String newNameFormat) {
- this.nameFormat = prepareForAssignment(this.nameFormat, newNameFormat);
- }
-
-
- public final void setUnknownAttributes(final AttributeMap newUnknownAttr) {
- this.unknownAttributes = newUnknownAttr;
- }
-
- @Override
- public XSBooleanValue isRequiredXSBoolean() {
- return XSBooleanValue.valueOf(isRequired);
- }
-
- @Override
- public void setIsRequired(Boolean aBoolean) {
- this.isRequired = String.valueOf(aBoolean);
- }
-
- @Override
- public void setIsRequired(XSBooleanValue xsBooleanValue) {
- this.isRequired = String.valueOf(xsBooleanValue);
- }
-
- @Override
- public Boolean isRequired() {
- return Boolean.parseBoolean(isRequired);
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java
deleted file mode 100644
index b85d4791..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.reqattr;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.opensaml.common.impl.AbstractSAMLObject;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.util.IndexedXMLObjectChildrenList;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes;
-
-public class EAAFRequestedAttributesImpl extends AbstractSAMLObject implements EAAFRequestedAttributes {
-
- private final IndexedXMLObjectChildrenList<XMLObject> indexedChildren;
-
- public EAAFRequestedAttributesImpl(String namespaceURI, String elementLocalName, String namespacePrefix) {
- super(namespaceURI, elementLocalName, namespacePrefix);
- indexedChildren = new IndexedXMLObjectChildrenList<XMLObject>(this);
- }
-
- @Override
- public List<XMLObject> getOrderedChildren() {
- final List<XMLObject> children = new ArrayList<XMLObject>();
- children.addAll(indexedChildren);
- return Collections.unmodifiableList(children);
-
- }
-
- @Override
- public List<EAAFRequestedAttribute> getAttributes() {
- return (List<EAAFRequestedAttribute>) indexedChildren
- .subList(EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME);
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java
new file mode 100644
index 00000000..e391bb31
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.reqattr;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.schema.XSBooleanValue;
+import org.opensaml.core.xml.util.AttributeMap;
+import org.opensaml.core.xml.util.XMLObjectChildrenList;
+import org.opensaml.saml.common.AbstractSAMLObject;
+
+public class EaafRequestedAttributeImpl extends AbstractSAMLObject
+ implements EaafRequestedAttribute {
+
+ private final XMLObjectChildrenList<XMLObject> attributeValues;
+ private String friendlyName;
+ private String isRequired;
+ private String name;
+ private String nameFormat;
+ private AttributeMap unknownAttributes;
+
+ /**
+ * Build an EAAF specific requested attribute.
+ *
+ * @param namespaceUri Attribute namespace
+ * @param elementLocalName Attribute name
+ * @param namespacePrefix Attribute namespace prefix
+ */
+ public EaafRequestedAttributeImpl(final String namespaceUri, final String elementLocalName,
+ final String namespacePrefix) {
+ super(namespaceUri, elementLocalName, namespacePrefix);
+ unknownAttributes = new AttributeMap(this);
+ attributeValues = new XMLObjectChildrenList<>(this);
+
+ }
+
+ @Override
+ public final List<XMLObject> getAttributeValues() {
+ return attributeValues;
+ }
+
+ @Override
+ public final String getFriendlyName() {
+ return friendlyName;
+ }
+
+ @Override
+ public final String getIsRequiredXsBoolean() {
+ return isRequired;
+ }
+
+ @Override
+ public final String getName() {
+ return name;
+ }
+
+ @Override
+ public final String getNameFormat() {
+ return nameFormat;
+ }
+
+ @Override
+ public final List<XMLObject> getOrderedChildren() {
+ final List<XMLObject> children = new ArrayList<>();
+ children.addAll(attributeValues);
+ return Collections.unmodifiableList(children);
+ }
+
+ @Override
+ public final AttributeMap getUnknownAttributes() {
+ return unknownAttributes;
+ }
+
+ @Override
+ public final void setFriendlyName(final String newFriendlyName) {
+ this.friendlyName = prepareForAssignment(this.friendlyName, newFriendlyName);
+ }
+
+ @Override
+ public void setIsRequired(final Boolean aboolean) {
+ this.isRequired = String.valueOf(aboolean);
+ }
+
+ @Override
+ public void setIsRequired(final XSBooleanValue xsBooleanValue) {
+ this.isRequired = String.valueOf(xsBooleanValue);
+ }
+
+ @Override
+ public final void setIsRequired(final String newIsRequired) {
+ isRequired = prepareForAssignment(this.isRequired, newIsRequired);
+
+ }
+
+ @Override
+ public final void setName(final String newName) {
+ this.name = prepareForAssignment(this.name, newName);
+ }
+
+ @Override
+ public final void setNameFormat(final String newNameFormat) {
+ this.nameFormat = prepareForAssignment(this.nameFormat, newNameFormat);
+ }
+
+ public final void setUnknownAttributes(final AttributeMap newUnknownAttr) {
+ this.unknownAttributes = newUnknownAttr;
+ }
+
+ @Override
+ public XSBooleanValue isRequiredXSBoolean() {
+ return XSBooleanValue.valueOf(isRequired);
+ }
+
+ @Override
+ public Boolean isRequired() {
+ return Boolean.parseBoolean(isRequired);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java
new file mode 100644
index 00000000..9c251233
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.reqattr;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.util.IndexedXMLObjectChildrenList;
+import org.opensaml.saml.common.AbstractSAMLObject;
+
+public class EaafRequestedAttributesImpl extends AbstractSAMLObject
+ implements EaafRequestedAttributes {
+
+ private final IndexedXMLObjectChildrenList<XMLObject> indexedChildren;
+
+ public EaafRequestedAttributesImpl(final String namespaceUri, final String elementLocalName,
+ final String namespacePrefix) {
+ super(namespaceUri, elementLocalName, namespacePrefix);
+ indexedChildren = new IndexedXMLObjectChildrenList<>(this);
+ }
+
+ @Override
+ public List<XMLObject> getOrderedChildren() {
+ final List<XMLObject> children = new ArrayList<>();
+ children.addAll(indexedChildren);
+ return Collections.unmodifiableList(children);
+
+ }
+
+ @Override
+ public List<EaafRequestedAttribute> getAttributes() {
+ return (List<EaafRequestedAttribute>) indexedChildren
+ .subList(EaafRequestedAttribute.DEFAULT_ELEMENT_NAME);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java
index acc5357e..26a5c5f6 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java
@@ -1,225 +1,328 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.RSAPrivateKey;
+import java.security.KeyStoreException;
+import java.security.Provider;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.xml.security.credential.Credential;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.x509.X509Credential;
-import org.opensaml.xml.signature.Signature;
-import org.opensaml.xml.signature.SignatureConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
+import javax.annotation.Nonnull;
+import javax.annotation.PostConstruct;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+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.utils.IPvp2CredentialProvider;
import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.KeyStoreX509CredentialAdapter;
-
-public abstract class AbstractCredentialProvider {
-
- private static final Logger log = LoggerFactory.getLogger(AbstractCredentialProvider.class);
-
- private KeyStore keyStore = null;
-
- /**
- * Get a friendlyName for this keyStore implementation
- * This friendlyName is used for logging
- *
- * @return keyStore friendlyName
- */
- public abstract String getFriendlyName();
-
- /**
- * Get KeyStore
- *
- * @return URL to the keyStore
- * @throws EAAFException
- */
- public abstract String getKeyStoreFilePath() throws EAAFException;
-
- /**
- * Get keyStore password
- *
- * @return Password of the keyStore
- */
- public abstract String getKeyStorePassword();
-
- /**
- * Get alias of key for metadata signing
- *
- * @return key alias
- */
- public abstract String getMetadataKeyAlias();
-
- /**
- * Get password of key for metadata signing
- *
- * @return key password
- */
- public abstract String getMetadataKeyPassword();
-
- /**
- * Get alias of key for request/response signing
- *
- * @return key alias
- */
- public abstract String getSignatureKeyAlias();
-
- /**
- * Get password of key for request/response signing
- *
- * @return key password
- */
- public abstract String getSignatureKeyPassword();
-
- /**
- * Get alias of key for IDP response encryption
- *
- * @return key alias
- */
- public abstract String getEncryptionKeyAlias();
-
- /**
- * Get password of key for IDP response encryption
- *
- * @return key password
- */
- public abstract String getEncryptionKeyPassword();
-
-
- public X509Credential getIDPMetaDataSigningCredential()
- throws CredentialsNotAvailableException {
- try {
-
- if (keyStore == null)
- keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),
- getKeyStorePassword());
-
- KeyStoreX509CredentialAdapter credentials = new KeyStoreX509CredentialAdapter(
- keyStore, getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray());
-
- credentials.setUsageType(UsageType.SIGNING);
- if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) {
- log.error(getFriendlyName() + " Metadata Signing credentials is not found or contains no PrivateKey.");
- throw new CredentialsNotAvailableException("config.27", new Object[]{getFriendlyName() + " Assertion Signing credentials (Alias: "
- + getMetadataKeyAlias() + ") is not found or contains no PrivateKey."});
-
- }
- return credentials;
- } catch (Exception e) {
- log.error("Failed to generate " + getFriendlyName() + " Metadata Signing credentials");
- e.printStackTrace();
- throw new CredentialsNotAvailableException("config.27", new Object[]{e.getMessage()}, e);
- }
- }
-
- public X509Credential getIDPAssertionSigningCredential()
- throws CredentialsNotAvailableException {
- try {
- if (keyStore == null)
- keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),
- getKeyStorePassword());
-
- KeyStoreX509CredentialAdapter credentials = new KeyStoreX509CredentialAdapter(
- keyStore, getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray());
-
- credentials.setUsageType(UsageType.SIGNING);
- if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) {
- log.error(getFriendlyName() + " Assertion Signing credentials is not found or contains no PrivateKey.");
- throw new CredentialsNotAvailableException("config.27", new Object[]{getFriendlyName() + " Assertion Signing credentials (Alias: "
- + getSignatureKeyAlias() + ") is not found or contains no PrivateKey."});
-
- }
-
- return (X509Credential) credentials;
- } catch (Exception e) {
- log.error("Failed to generate " + getFriendlyName() + " Assertion Signing credentials");
- e.printStackTrace();
- throw new CredentialsNotAvailableException("config.27", new Object[]{e.getMessage()}, e);
- }
- }
-
- public X509Credential getIDPAssertionEncryptionCredential()
- throws CredentialsNotAvailableException {
- try {
- if (keyStore == null)
- keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(),
- getKeyStorePassword());
-
- //if no encryption key is configured return null
- if (StringUtils.isEmpty(getEncryptionKeyAlias()))
- return null;
-
- KeyStoreX509CredentialAdapter credentials = new KeyStoreX509CredentialAdapter(
- keyStore, getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray());
-
- credentials.setUsageType(UsageType.ENCRYPTION);
-
- if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) {
- log.error(getFriendlyName() + " Assertion Encryption credentials is not found or contains no PrivateKey.");
- throw new CredentialsNotAvailableException("config.27", new Object[]{getFriendlyName() + " Assertion Encryption credentials (Alias: "
- + getEncryptionKeyAlias() + ") is not found or contains no PrivateKey."});
-
- }
-
- return (X509Credential) credentials;
-
- } catch (Exception e) {
- log.error("Failed to generate " + getFriendlyName() + " Assertion Encryption credentials");
- e.printStackTrace();
- throw new CredentialsNotAvailableException("config.27", new Object[]{e.getMessage()}, e);
- }
- }
-
- public static Signature getIDPSignature(Credential credentials) {
- PrivateKey privatekey = credentials.getPrivateKey();
- Signature signer = SAML2Utils.createSAMLObject(Signature.class);
-
- if (privatekey instanceof RSAPrivateKey) {
- signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
-
- } else if (privatekey instanceof ECPrivateKey) {
- signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256);
-
- } else {
- log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId() + " credential.");
-
-
- }
-
- signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
- signer.setSigningCredential(credentials);
- return signer;
-
- }
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafKeyStoreX509CredentialAdapter;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.xml.security.algorithms.JCEMapper;
+import org.opensaml.security.credential.UsageType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ResourceLoader;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public abstract class AbstractCredentialProvider implements IPvp2CredentialProvider {
+
+ private static final String TRUSTED_CERTIFICATES_OPERATION = "Trusted Certificate Entries";
+
+ @Autowired
+ protected ResourceLoader resourceLoader;
+ @Autowired
+ protected IConfiguration basicConfig;
+
+ @Autowired
+ private EaafKeyStoreFactory keyStoreFactory;
+
+ private Pair<KeyStore, Provider> keyStore = null;
+
+ /**
+ * Get a friendlyName for this keyStore implementation This friendlyName is used
+ * for logging.
+ *
+ * @return keyStore friendlyName
+ */
+ public final String getFriendlyName() {
+ try {
+ return getBasicKeyStoreConfig().getFriendlyName();
+
+ } catch (final EaafConfigurationException e) {
+ return "No KeyStoreName";
+
+ }
+
+ }
+
+ /**
+ * Get the basic KeyStore configuration object for this SAML2 credential.
+ *
+ * @return KeyStore configuration object
+ * @throws EaafConfigurationException In case of a configuration error
+ */
+ @Nonnull
+ public abstract KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException;
+
+ /**
+ * Get alias of key for metadata signing.
+ *
+ * @return key alias
+ */
+ public abstract String getMetadataKeyAlias();
+
+ /**
+ * Get password of key for metadata signing.
+ *
+ * @return key password
+ */
+ public abstract String getMetadataKeyPassword();
+
+ /**
+ * Get alias of key for request/response signing.
+ *
+ * @return key alias
+ */
+ public abstract String getSignatureKeyAlias();
+
+ /**
+ * Get password of key for request/response signing.
+ *
+ * @return key password
+ */
+ public abstract String getSignatureKeyPassword();
+
+ /**
+ * Get alias of key for IDP response encryption.
+ *
+ * @return key alias
+ */
+ public abstract String getEncryptionKeyAlias();
+
+ /**
+ * Get password of key for IDP response encryption.
+ *
+ * @return key password
+ */
+ public abstract String getEncryptionKeyPassword();
+
+ /**
+ * Get Credentials to sign metadata.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of a credential error
+ */
+ @Override
+ public EaafX509Credential getMetaDataSigningCredential() throws CredentialsNotAvailableException {
+ try {
+ final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(
+ keyStore.getFirst(), getMetadataKeyAlias(),
+ getPassCharArrayOrNull(getMetadataKeyPassword()), getFriendlyName());
+ credentials.setUsageType(UsageType.SIGNING);
+ credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials));
+ credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials));
+ return credentials;
+
+ } catch (final Exception e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01",
+ new Object[] { getFriendlyName(), getMetadataKeyAlias() }, e);
+
+ }
+ }
+
+ /**
+ * Get Credentials to sign SAML2 messages, like AuthnRequest, Response,
+ * Assertions as some examples.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of a credential error
+ */
+ @Override
+ public EaafX509Credential getMessageSigningCredential() throws CredentialsNotAvailableException {
+ try {
+ final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(
+ keyStore.getFirst(), getSignatureKeyAlias(),
+ getPassCharArrayOrNull(getSignatureKeyPassword()), getFriendlyName());
+ credentials.setUsageType(UsageType.SIGNING);
+ credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials));
+ credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials));
+ return credentials;
+
+ } catch (final Exception e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01",
+ new Object[] { getFriendlyName(), getSignatureKeyAlias() }, e);
+
+ }
+ }
+
+ /**
+ * Get Credentials to encrypt messages, like Assertion as example.
+ *
+ * @return Credentials
+ * @throws CredentialsNotAvailableException In case of a credential error
+ */
+ @Override
+ public EaafX509Credential getMessageEncryptionCredential()
+ throws CredentialsNotAvailableException {
+ // if no encryption key is configured return null
+ if (StringUtils.isEmpty(getEncryptionKeyAlias())) {
+ return null;
+ }
+
+ try {
+ final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(
+ keyStore.getFirst(), getEncryptionKeyAlias(),
+ getPassCharArrayOrNull(getEncryptionKeyPassword()), getFriendlyName());
+ credentials.setUsageType(UsageType.ENCRYPTION);
+ credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials));
+ credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials));
+ return credentials;
+
+ } catch (final Exception e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01",
+ new Object[] { getFriendlyName(), getEncryptionKeyAlias() }, e);
+
+ }
+
+ }
+
+ /**
+ * Get a List of trusted {@link X509Certificate} that are available in this
+ * KeyStore.
+ *
+ * @return List of trusted {@link X509Certificate}, or an emptry {@link List} if
+ * no certificates are available
+ * @throws CredentialsNotAvailableException In case of a KeyStore error
+ */
+ @Override
+ @Nonnull
+ public List<X509Certificate> getTrustedCertificates()
+ throws CredentialsNotAvailableException {
+ final List<X509Certificate> result = new ArrayList<>();
+
+ try {
+ final Enumeration<String> aliases = keyStore.getFirst().aliases();
+ while (aliases.hasMoreElements()) {
+ final String el = aliases.nextElement();
+ log.trace("Process TrustStoreEntry: " + el);
+ if (keyStore.getFirst().isCertificateEntry(el)) {
+ final Certificate cert = keyStore.getFirst().getCertificate(el);
+ if (cert != null && cert instanceof X509Certificate) {
+ result.add((X509Certificate) cert);
+
+ } else {
+ log.info("Can not process entry: {}. Reason: {}",
+ el, cert != null ? cert.getType() : "cert is null");
+
+ }
+ }
+ }
+ } catch (final KeyStoreException e) {
+ throw new CredentialsNotAvailableException("internal.pvp.01",
+ new Object[] { getFriendlyName(), TRUSTED_CERTIFICATES_OPERATION }, e);
+ }
+
+ return Collections.unmodifiableList(result);
+
+ }
+
+ @PostConstruct
+ private void initialize() throws Exception {
+ try {
+ final KeyStoreConfiguration keyStoreConfig = getBasicKeyStoreConfig();
+ keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig);
+
+ if (JCEMapper.getProviderId() != null && keyStore.getSecond() != null
+ && !JCEMapper.getProviderId().equals(keyStore.getSecond().getName())) {
+ log.error("OpenSAML3.x can ONLY use a single type of CryptoProvider in an application. "
+ + "Can NOT set: {}, because {} was already set", keyStore.getSecond().getName(),
+ JCEMapper.getProviderId());
+ throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_06,
+ new Object[] { keyStoreConfig.getFriendlyName(),
+ "OpenSAML3.x can ONLY use a single type of CryptoProvider" });
+
+ }
+
+ // Set JCEMapper only in case of HSM based KeyStores because Software KeyStores
+ // can use
+ // the default SecurityProvider system in OpenSAML3.x signing engine
+ if (keyStore.getSecond() != null
+ && JCEMapper.getProviderId() == null) {
+ log.info("Register CryptoProvider: {} as defaut for OpenSAML3.x",
+ keyStore.getSecond().getName());
+ JCEMapper.setProviderId(keyStore.getSecond().getName());
+
+ }
+
+ } catch (final EaafException e) {
+ log.error("Can not initialize KeyStore for eIDAS authentication client.", e);
+ throw e;
+
+ }
+ }
+
+ private String selectSigningAlgorithm(EaafKeyStoreX509CredentialAdapter credentials)
+ throws SamlSigningException {
+ return Saml2Utils.getKeyOperationAlgorithmFromCredential(
+ credentials,
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA),
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG,
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC));
+ }
+
+ private String selectKeyEncryptionAlgorithm(EaafKeyStoreX509CredentialAdapter credentials)
+ throws SamlSigningException {
+ return Saml2Utils.getKeyOperationAlgorithmFromCredential(
+ credentials,
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA),
+ basicConfig.getBasicConfiguration(
+ PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC));
+ }
+
+ private char[] getPassCharArrayOrNull(String metadataKeyPassword) {
+ char[] keyPassChar = null;
+ if (metadataKeyPassword != null) {
+ keyPassChar = metadataKeyPassword.toCharArray();
+
+ }
+
+ return keyPassChar;
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java
deleted file mode 100644
index 8e7183d3..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
-
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
-import at.gv.egiz.eaaf.modules.pvp2.exception.QAANotAllowedException;
-
-/**
- * @author tlenz
- *
- */
-public class QAALevelVerifier {
-
- private static final Logger log = LoggerFactory.getLogger(QAALevelVerifier.class);
-
- private static boolean verifyQAALevel(String qaaAuth, String requiredLoA, String matchingMode) throws QAANotAllowedException {
- //to MINIMUM machting
- if (EAAFConstants.EIDAS_LOA_MATCHING_MINIMUM.equals(matchingMode)) {
- log.trace("Perfom LoA matching in 'MINIMUM' mode ... ");
- if (EAAFConstants.EIDAS_LOA_LOW.equals(requiredLoA) &&
- (EAAFConstants.EIDAS_LOA_LOW.equals(qaaAuth) ||
- EAAFConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth) ||
- EAAFConstants.EIDAS_LOA_HIGH.equals(qaaAuth))
- )
- return true;
-
- else if (EAAFConstants.EIDAS_LOA_SUBSTANTIAL.equals(requiredLoA) &&
- (EAAFConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth) ||
- EAAFConstants.EIDAS_LOA_HIGH.equals(qaaAuth))
- )
- return true;
-
- else if (EAAFConstants.EIDAS_LOA_HIGH.equals(requiredLoA) && EAAFConstants.EIDAS_LOA_HIGH.equals(qaaAuth))
- return true;
-
- } else if (EAAFConstants.EIDAS_LOA_MATCHING_EXACT.equals(matchingMode)) {
- //to EXACT matching
- log.trace("Perfom LoA matching in 'EXACT' mode ... ");
- if (qaaAuth.equals(requiredLoA)) {
- log.debug("Required LoA fits LoA from authentication. Continue auth process ... ");
- return true;
-
- }
-
- } else {
- log.warn("LoA matching-mode:" + matchingMode + " is NOT supported by this implementation");
- throw new QAANotAllowedException(qaaAuth, requiredLoA, matchingMode);
-
- }
-
- return false;
-
- }
-
- public static void verifyQAALevel(String qaaAuth, List<String> requiredLoAs, String matchingMode) throws QAANotAllowedException {
- log.trace("Starting LoA verification: authLoA: " + qaaAuth
- + " requiredLoA: " + StringUtils.join(requiredLoAs, "|")
- + " matchingMode: " + matchingMode);
-
- boolean hasMatch = false;
- for (String loa : requiredLoAs) {
- if (verifyQAALevel(qaaAuth, loa, matchingMode))
- hasMatch = true;
-
- }
-
- if (!hasMatch)
- throw new QAANotAllowedException(qaaAuth, StringUtils.join(requiredLoAs, "|"), matchingMode);
-
- else
- log.debug("Requesed LoA fits LoA from authentication. Continue auth process ... ");
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java
new file mode 100644
index 00000000..ca6f29e4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
+
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotAllowedException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EAAF LoA Level verifier checks if requested LoA matchs to LoA of
+ * authentication.
+ *
+ *
+ * @author tlenz
+ *
+ */
+public class QaaLevelVerifier {
+
+ private static final Logger log = LoggerFactory.getLogger(QaaLevelVerifier.class);
+
+ private static boolean verifyQaaLevel(final String qaaAuth, final String requiredLoA,
+ final String matchingMode) throws QaaNotAllowedException {
+ // to MINIMUM machting
+ if (EaafConstants.EIDAS_LOA_MATCHING_MINIMUM.equals(matchingMode)) {
+ log.trace("Perfom LoA matching in 'MINIMUM' mode ... ");
+ if (EaafConstants.EIDAS_LOA_LOW.equals(requiredLoA)
+ && (EaafConstants.EIDAS_LOA_LOW.equals(qaaAuth)
+ || EaafConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth)
+ || EaafConstants.EIDAS_LOA_HIGH.equals(qaaAuth))) {
+ return true;
+ } else if (EaafConstants.EIDAS_LOA_SUBSTANTIAL.equals(requiredLoA)
+ && (EaafConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth)
+ || EaafConstants.EIDAS_LOA_HIGH.equals(qaaAuth))) {
+ return true;
+ } else if (EaafConstants.EIDAS_LOA_HIGH.equals(requiredLoA)
+ && EaafConstants.EIDAS_LOA_HIGH.equals(qaaAuth)) {
+ return true;
+ }
+
+ } else if (EaafConstants.EIDAS_LOA_MATCHING_EXACT.equals(matchingMode)) {
+ // to EXACT matching
+ log.trace("Perfom LoA matching in 'EXACT' mode ... ");
+ if (qaaAuth.equals(requiredLoA)) {
+ log.debug("Required LoA fits LoA from authentication. Continue auth process ... ");
+ return true;
+
+ }
+
+ } else {
+ log.warn("LoA matching-mode:" + matchingMode + " is NOT supported by this implementation");
+ throw new QaaNotAllowedException(qaaAuth, requiredLoA, matchingMode);
+
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Check LoA level.
+ *
+ * @param qaaAuth LoA of authentication
+ * @param requiredLoAs List of allowed LoA levels
+ * @param matchingMode LoA matching mode
+ * @throws QaaNotAllowedException If LoA does not match
+ */
+ public static void verifyQaaLevel(final String qaaAuth, final List<String> requiredLoAs,
+ final String matchingMode) throws QaaNotAllowedException {
+ log.trace("Starting LoA verification: authLoA: " + qaaAuth + " requiredLoA: "
+ + StringUtils.join(requiredLoAs, "|") + " matchingMode: " + matchingMode);
+
+ boolean hasMatch = false;
+ for (final String loa : requiredLoAs) {
+ if (verifyQaaLevel(qaaAuth, loa, matchingMode)) {
+ hasMatch = true;
+ }
+
+ }
+
+ if (!hasMatch) {
+ throw new QaaNotAllowedException(qaaAuth, StringUtils.join(requiredLoAs, "|"), matchingMode);
+ } else {
+ log.debug("Requesed LoA fits LoA from authentication. Continue auth process ... ");
+ }
+
+ }
+}
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
deleted file mode 100644
index d33ee6c6..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SAML2Utils.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
-
-import java.io.IOException;
-import java.security.NoSuchAlgorithmException;
-import java.util.List;
-
-import javax.xml.namespace.QName;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.Validator;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.Configuration;
-import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.core.Status;
-import org.opensaml.saml2.core.StatusCode;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.ws.soap.soap11.Body;
-import org.opensaml.ws.soap.soap11.Envelope;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.XMLObjectBuilderFactory;
-import org.opensaml.xml.io.Marshaller;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.schema.XSString;
-import org.opensaml.xml.schema.impl.XSStringBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-
-import at.gv.egiz.eaaf.core.impl.utils.Random;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-
-public class SAML2Utils {
- private static final Logger log = LoggerFactory.getLogger(SAML2Utils.class);
-
- public static <T> T createSAMLObject(final Class<T> clazz) {
- try {
- XMLObjectBuilderFactory builderFactory = Configuration
- .getBuilderFactory();
-
- QName defaultElementName = (QName) clazz.getDeclaredField(
- "DEFAULT_ELEMENT_NAME").get(null);
- @SuppressWarnings("unchecked")
- T object = (T) builderFactory.getBuilder(defaultElementName)
- .buildObject(defaultElementName);
- return object;
- } catch (Throwable e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public static String getSecureIdentifier() {
- return "_".concat(Random.nextHexRandom16());
-
- /*Bug-Fix: There are open problems with RandomNumberGenerator via Java SPI and Java JDK 8.121
- * Generation of a 16bit Random identifier FAILES with an Caused by: java.lang.ArrayIndexOutOfBoundsException
- * Caused by: java.lang.ArrayIndexOutOfBoundsException
- at iaik.security.random.o.engineNextBytes(Unknown Source)
- at iaik.security.random.SecRandomSpi.engineNextBytes(Unknown Source)
- at java.security.SecureRandom.nextBytes(SecureRandom.java:468)
- at org.opensaml.common.impl.SecureRandomIdentifierGenerator.generateIdentifier(SecureRandomIdentifierGenerator.java:62)
- at org.opensaml.common.impl.SecureRandomIdentifierGenerator.generateIdentifier(SecureRandomIdentifierGenerator.java:56)
- at at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils.getSecureIdentifier(SAML2Utils.java:69)
- */
- //return idGenerator.generateIdentifier();
- }
-
- private static SecureRandomIdentifierGenerator idGenerator;
-
- private static DocumentBuilder builder;
- static {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(true);
- try {
- builder = factory.newDocumentBuilder();
- } catch (ParserConfigurationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- try {
- idGenerator = new SecureRandomIdentifierGenerator();
- } catch(NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- }
-
- public static Document asDOMDocument(XMLObject object) throws IOException,
- MarshallingException, TransformerException {
- Document document = builder.newDocument();
- Marshaller out = Configuration.getMarshallerFactory().getMarshaller(
- object);
- out.marshall(object, document);
- return document;
- }
-
- public static Status getSuccessStatus() {
- Status status = SAML2Utils.createSAMLObject(Status.class);
- StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
- statusCode.setValue(StatusCode.SUCCESS_URI);
- status.setStatusCode(statusCode);
- return status;
- }
-
- public static int getDefaultAssertionConsumerServiceIndex(SPSSODescriptor spSSODescriptor) {
-
- List<AssertionConsumerService> assertionConsumerList = spSSODescriptor.getAssertionConsumerServices();
-
- for (AssertionConsumerService el : assertionConsumerList) {
- if (el.isDefault())
- return el.getIndex();
-
- }
-
- return 0;
- }
-
- public static Envelope buildSOAP11Envelope(XMLObject payload) {
- XMLObjectBuilderFactory bf = Configuration.getBuilderFactory();
- Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME).buildObject(Envelope.DEFAULT_ELEMENT_NAME);
- Body body = (Body) bf.getBuilder(Body.DEFAULT_ELEMENT_NAME).buildObject(Body.DEFAULT_ELEMENT_NAME);
-
- body.getUnknownXMLObjects().add(payload);
- envelope.setBody(body);
-
- return envelope;
- }
-
- public static EAAFRequestedAttribute generateReqAuthnAttributeSimple(Attribute attr, boolean isRequired, String value) {
- EAAFRequestedAttribute requested = SAML2Utils.createSAMLObject(EAAFRequestedAttribute.class);
- requested.setName(attr.getName());
- requested.setNameFormat(attr.getNameFormat());
- requested.setFriendlyName(attr.getFriendlyName());
- requested.setIsRequired(String.valueOf(isRequired));
- List<XMLObject> attributeValues = requested.getAttributeValues();
- if (StringUtils.isNotEmpty(value)) {
- XMLObject attributeValueForRequest = createAttributeValue(PVPConstants.EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE, value);
- attributeValues.add(attributeValueForRequest);
- }
- return requested;
-
- }
-
- public static void schemeValidation(XMLObject xmlObject) throws Exception {
- try {
- Schema test = SAMLSchemaBuilder.getSAML11Schema();
- Validator val = test.newValidator();
- DOMSource source = new DOMSource(xmlObject.getDOM());
- val.validate(source);
- log.debug("SAML2 Scheme validation successful");
- return;
-
- } catch (Exception e) {
- log.warn("SAML2 scheme validation FAILED.", e);
- throw e;
-
- }
- }
-
- private static XMLObject createAttributeValue(QName attributeValueType, String value) {
- XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME);
- XSString stringValue = stringBuilder.buildObject(attributeValueType, XSString.TYPE_NAME);
- stringValue.setValue(value);
- return stringValue;
-
- }
-}
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
new file mode 100644
index 00000000..5059b1fb
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.XMLObjectBuilderFactory;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Marshaller;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.Unmarshaller;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.core.xml.schema.impl.XSStringBuilder;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.common.SAMLObjectContentReference;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.Status;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.soap.soap11.Body;
+import org.opensaml.soap.soap11.Envelope;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.SignatureSigningConfiguration;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager;
+import org.opensaml.xmlsec.keyinfo.NamedKeyInfoGeneratorManager;
+import org.opensaml.xmlsec.keyinfo.impl.BasicKeyInfoGeneratorFactory;
+import org.opensaml.xmlsec.signature.KeyInfo;
+import org.opensaml.xmlsec.signature.SignableXMLObject;
+import org.opensaml.xmlsec.signature.Signature;
+import org.opensaml.xmlsec.signature.support.ContentReference;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.Signer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import net.shibboleth.utilities.java.support.xml.QNameSupport;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+
+public class Saml2Utils {
+ private static final Logger log = LoggerFactory.getLogger(Saml2Utils.class);
+
+ private static DocumentBuilder builder;
+ private static SAMLSchemaBuilder schemaBuilder;
+
+ static {
+ schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
+
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+
+ try {
+ builder = factory.newDocumentBuilder();
+
+ } catch (final ParserConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Sign a OpenSAML 3.x object with a {@link X509Credential}. <br>
+ * <p>
+ * This method used {@link PvpConstants.DEFAULT_SIGNING_METHODE_RSA} or
+ * {@link PvpConstants.DEFAULT_SIGNING_METHODE_EC} as algorithm
+ * </p>
+ *
+ * @param <T> {@link SignableXMLObject}
+ * @param toSign object that should be signed
+ * @param signingCredential Credentials that should be used for signing
+ * @param injectCertificate true, if certificate should be part of the signature
+ * @return Signed object
+ * @throws SamlSigningException In case of a signing error
+ */
+ public static <T extends SignableXMLObject> T signSamlObject(@Nonnull T toSign,
+ @Nonnull EaafX509Credential signingCredential, boolean injectCertificate) throws SamlSigningException {
+
+ try {
+ final String usedSigAlg = signingCredential.getSignatureAlgorithmForSigning();
+ final Signature signature = createSignature(signingCredential, usedSigAlg, injectCertificate);
+ toSign.setSignature(signature);
+
+ final String digestAlgorithm = getDigestAlgorithm(usedSigAlg);
+ final List<ContentReference> contentReferences = signature.getContentReferences();
+ if (!CollectionUtils.isEmpty(contentReferences)) {
+ ((SAMLObjectContentReference) contentReferences.get(0)).setDigestAlgorithm(digestAlgorithm);
+
+ } else {
+ log.error("Unable to set DigestMethodAlgorithm - algorithm {} not set", digestAlgorithm);
+
+ }
+
+ log.trace("Marshall samlToken.");
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(toSign).marshall(toSign);
+
+ log.trace("Sign samlToken.");
+ Signer.signObject(signature);
+
+ return toSign;
+
+ } catch (final SignatureException | MarshallingException | SecurityException e) {
+ throw new SamlSigningException("internal.pvp.96",
+ new Object[] { signingCredential.getEntityId(), e.getMessage() }, e);
+
+ }
+
+ }
+
+ /**
+ * SAML2 message unmarshaller that performs schema validation before unmarshall
+ * the message.
+ *
+ * @param messageStream SAML2 message that shoulld be unmarshalled
+ * @return OpenSAML XML object
+ * @throws MessageDecodingException In case of a schema-validation or
+ * unmarshalling error
+ */
+ public static XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException {
+ try {
+ final Element samlElement = DomUtils.parseXmlValidating(messageStream);
+
+ if (log.isTraceEnabled()) {
+ log.trace("Resultant DOM message was:");
+ log.trace(SerializeSupport.nodeToString(samlElement));
+ }
+
+ log.debug("Unmarshalling DOM parsed from InputStream");
+ final Unmarshaller unmarshaller = XMLObjectSupport.getUnmarshaller(samlElement);
+ if (unmarshaller == null) {
+ log.error("Unable to unmarshall InputStream, no unmarshaller registered for element "
+ + QNameSupport.getNodeQName(samlElement));
+ throw new UnmarshallingException(
+ "Unable to unmarshall InputStream, no unmarshaller registered for element "
+ + QNameSupport.getNodeQName(samlElement));
+ }
+
+ final XMLObject message = unmarshaller.unmarshall(samlElement);
+
+ log.debug("InputStream succesfully unmarshalled");
+
+ return message;
+
+ } catch (final UnmarshallingException e) {
+ log.error("Error unmarshalling message from input stream", e);
+ throw new MessageDecodingException("Error unmarshalling message from input stream", e);
+
+ } catch (ParserConfigurationException | SAXException e) {
+ log.warn("Message schema-validation failed.");
+ throw new MessageDecodingException("Message schema-validation failed.",
+ new SchemaValidationException("internal.pvp.03", new Object[] { e.getMessage() }, e));
+
+ } catch (final IOException e) {
+ log.error("Error read message from input stream", e);
+ throw new MessageDecodingException("Error read message from input stream", e);
+
+ }
+ }
+
+ /**
+ * Select signature algorithm for a given credential.
+ *
+ * @param credentials {@link X509Credential} that will be used for key operations
+ * @param rsaSigAlgorithm RSA based algorithm that should be used in
+ * case of RSA credential
+ * @param ecSigAlgorithm EC based algorithm that should be used in case
+ * of RSA credential
+ * @return either the RSA based algorithm or the EC based algorithm
+ * @throws SamlSigningException In case of an unsupported credential
+ */
+ public static String getKeyOperationAlgorithmFromCredential(X509Credential credentials,
+ String rsaSigAlgorithm, String ecSigAlgorithm) throws SamlSigningException {
+ final PrivateKey privatekey = credentials.getPrivateKey();
+ final PublicKey publickey = credentials.getPublicKey();
+ if (privatekey instanceof RSAPrivateKey
+ || publickey instanceof RSAPublicKey) {
+ return rsaSigAlgorithm;
+
+ } else if (privatekey instanceof ECPrivateKey
+ || publickey instanceof ECPublicKey) {
+ return ecSigAlgorithm;
+
+ } else {
+ log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId()
+ + " credential.");
+ throw new SamlSigningException("internal.pvp.97",
+ new Object[] { credentials.getEntityId(),
+ privatekey != null ? privatekey.getClass().getName() : publickey.getClass().getName()
+ });
+
+ }
+ }
+
+ /**
+ * Select a digest algorithm for a already selected signing algorithm.
+ *
+ * @param signatureAlgorithmName Signing algorithm that will be used
+ * @return Digest algorithm identifier
+ */
+ public static String getDigestAlgorithm(String signatureAlgorithmName) {
+ if (StringUtils.isBlank(signatureAlgorithmName)) {
+ return PvpConstants.DEFAULT_DIGESTMETHODE;
+ }
+
+ final String canonicalAlgorithm = signatureAlgorithmName.trim();
+ final String digestAlgorithm = PvpConstants.SIGNATURE_TO_DIGEST_ALGORITHM_MAP.get(canonicalAlgorithm);
+ if (null != digestAlgorithm) {
+ return digestAlgorithm;
+
+ }
+
+ log.warn("Signing algorithm: {} does not contain a known digist algorithm. Use: {} as default",
+ signatureAlgorithmName, PvpConstants.DEFAULT_DIGESTMETHODE);
+ return PvpConstants.DEFAULT_DIGESTMETHODE;
+
+ }
+
+ /**
+ * Get a {@link KeyInfoGenerator} that injects key information into XML
+ * signature.
+ *
+ * @param credential @link X509Credential} that will be used for signing
+ * @param injectCertificate Set <code>true</code> if the certificate should be
+ * added to KeyInfo
+ * @return Generator for a XML signature key-information
+ */
+ public static KeyInfoGenerator getKeyInfoGenerator(X509Credential credential, boolean injectCertificate) {
+ // OpenSAML3 only support RSA and DSA for direct key injection
+ KeyInfoGeneratorFactory keyInfoGenFac = null;
+ if (injectCertificate || credential.getPublicKey() instanceof ECPublicKey) {
+ final SignatureSigningConfiguration secConfiguration = SecurityConfigurationSupport
+ .getGlobalSignatureSigningConfiguration();
+ final NamedKeyInfoGeneratorManager keyInfoManager = secConfiguration.getKeyInfoGeneratorManager();
+ final KeyInfoGeneratorManager keyInfoGenManager = keyInfoManager.getDefaultManager();
+ keyInfoGenFac = keyInfoGenManager.getFactory(credential);
+
+ } else {
+ keyInfoGenFac = createKeyInfoWithoutCertificate();
+
+ }
+
+ return keyInfoGenFac.newInstance();
+
+ }
+
+ /**
+ * Create a SAML2 object.
+ *
+ * @param <T> SAML2 object class
+ * @param clazz object class
+ * @return SAML2 object
+ */
+ public static <T> T createSamlObject(final Class<T> clazz) {
+ try {
+ final XMLObjectBuilderFactory builderFactory =
+ XMLObjectProviderRegistrySupport.getBuilderFactory();
+
+ final QName defaultElementName =
+ (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
+ @SuppressWarnings("unchecked")
+ final T object =
+ (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);
+ return object;
+ } catch (final Throwable e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Get a new SAML2 conform random value.
+ *
+ * @return
+ */
+ public static String getSecureIdentifier() {
+ return "_".concat(Random.nextHexRandom16());
+
+ }
+
+ /**
+ * Transform SAML2 Object to Element.
+ *
+ * @param object SAML2 object
+ * @return Element
+ * @throws IOException In case of an transformation error
+ * @throws MarshallingException In case of an transformation error
+ * @throws TransformerException In case of an transformation error
+ */
+ public static Document asDomDocument(final XMLObject object)
+ throws IOException, MarshallingException, TransformerException {
+ final Document document = builder.newDocument();
+ final Marshaller out =
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
+ out.marshall(object, document);
+ return document;
+ }
+
+ /**
+ * Build success status element.
+ *
+ * @return
+ */
+ public static Status getSuccessStatus() {
+ final Status status = Saml2Utils.createSamlObject(Status.class);
+ final StatusCode statusCode = Saml2Utils.createSamlObject(StatusCode.class);
+ statusCode.setValue(StatusCode.SUCCESS);
+ status.setStatusCode(statusCode);
+ return status;
+ }
+
+ /**
+ * Get AssertionConsumerService Index from metadata element.
+ *
+ * @param spSsoDescriptor metadata element
+ * @return
+ */
+ public static int getDefaultAssertionConsumerServiceIndex(final SPSSODescriptor spSsoDescriptor) {
+
+ final List<AssertionConsumerService> assertionConsumerList =
+ spSsoDescriptor.getAssertionConsumerServices();
+
+ for (final AssertionConsumerService el : assertionConsumerList) {
+ if (el.isDefault()) {
+ return el.getIndex();
+ }
+
+ }
+
+ return 0;
+ }
+
+ /**
+ * Build SOAP11 body from SAML2 object.
+ *
+ * @param payload SAML2 object
+ * @return
+ */
+ public static Envelope buildSoap11Envelope(final XMLObject payload) {
+ final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();
+ final Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME)
+ .buildObject(Envelope.DEFAULT_ELEMENT_NAME);
+ final Body body =
+ (Body) bf.getBuilder(Body.DEFAULT_ELEMENT_NAME).buildObject(Body.DEFAULT_ELEMENT_NAME);
+
+ body.getUnknownXMLObjects().add(payload);
+ envelope.setBody(body);
+
+ return envelope;
+ }
+
+ /**
+ * Generate EAAF specific requested attribute.
+ *
+ * @param attr SAML2 attribute definition
+ * @param isRequired is-mandatory flag
+ * @param value Attribute value
+ * @return
+ */
+ public static EaafRequestedAttribute generateReqAuthnAttributeSimple(
+ final Attribute attr, final boolean isRequired, final String value) {
+ final EaafRequestedAttribute requested =
+ Saml2Utils.createSamlObject(EaafRequestedAttribute.class);
+ requested.setName(attr.getName());
+ requested.setNameFormat(attr.getNameFormat());
+ requested.setFriendlyName(attr.getFriendlyName());
+ requested.setIsRequired(String.valueOf(isRequired));
+ final List<XMLObject> attributeValues = requested.getAttributeValues();
+ if (StringUtils.isNotEmpty(value)) {
+ final XMLObject attributeValueForRequest =
+ createAttributeValue(PvpConstants.EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE, value);
+ attributeValues.add(attributeValueForRequest);
+ }
+ return requested;
+
+ }
+
+ /**
+ * Perform XML schema-validation on SAML2 object.
+ *
+ * @param xmlObject SAML2 object
+ * @throws Exception In case of a validation error
+ */
+ public static void schemeValidation(final XMLObject xmlObject) throws Exception {
+ try {
+
+ final Schema test = schemaBuilder.getSAMLSchema();
+ final Validator val = test.newValidator();
+ final DOMSource source = new DOMSource(xmlObject.getDOM());
+ val.validate(source);
+ log.debug("SAML2 Scheme validation successful");
+ return;
+
+ } catch (final Exception e) {
+ log.warn("SAML2 scheme validation FAILED.", e);
+ throw e;
+
+ }
+ }
+
+ private static XMLObject createAttributeValue(final QName attributeValueType,
+ final String value) {
+ final XSStringBuilder stringBuilder = (XSStringBuilder) XMLObjectProviderRegistrySupport
+ .getBuilderFactory().getBuilder(XSString.TYPE_NAME);
+ final XSString stringValue = stringBuilder.buildObject(attributeValueType, XSString.TYPE_NAME);
+ stringValue.setValue(value);
+ return stringValue;
+
+ }
+
+ private static Signature createSignature(X509Credential signingCredential,
+ String usedSigAlg, boolean injectCertificate)
+ throws SecurityException, SamlSigningException {
+ log.trace("Generating OpenSAML signature object ... ");
+ final Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory()
+ .getBuilder(Signature.DEFAULT_ELEMENT_NAME)
+ .buildObject(Signature.DEFAULT_ELEMENT_NAME);
+ signature.setSigningCredential(signingCredential);
+ signature.setSignatureAlgorithm(usedSigAlg);
+ final KeyInfo keyInfo = getKeyInfoGenerator(signingCredential, injectCertificate).generate(
+ signingCredential);
+ signature.setKeyInfo(keyInfo);
+ signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ return signature;
+
+ }
+
+ private static KeyInfoGeneratorFactory createKeyInfoWithoutCertificate() {
+ final KeyInfoGeneratorFactory keyInfoGenFac = new BasicKeyInfoGeneratorFactory();
+ ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitPublicKeyValue(true);
+ ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitEntityIDAsKeyName(true);
+ ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitKeyNames(true);
+ ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitPublicDEREncodedKeyValue(true);
+ return keyInfoGenFac;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java
new file mode 100644
index 00000000..2e02bf22
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java
@@ -0,0 +1,33 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.utils;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.servlet.http.HttpServletRequest;
+
+public class SamlHttpUtils {
+
+ /**
+ * Always read the last parameter with this name from request to get a strict
+ * deterministic behavior. <br>
+ * <br>
+ * <b><i>If more than one parameters with the same name exists, this method
+ * always select the last parameter value.</i></b>
+ *
+ * @param request Incoming http request
+ * @param paramName Name of the http parameter
+ * @return the last parameter value with this name, or <code>null</code> if the
+ * parameter not exists
+ */
+ @Nullable
+ public static String getLastParameterFromRequest(@Nonnull HttpServletRequest request,
+ @Nonnull String paramName) {
+ final String[] values = request.getParameterValues(paramName);
+ if (values != null && values.length > 0) {
+ return values[values.length - 1];
+
+ }
+
+ return null;
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java
deleted file mode 100644
index 30b7dcf9..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.validation;
-
-import org.opensaml.common.binding.decoding.URIComparator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-public class EAAFURICompare implements URIComparator {
- private static final Logger log = LoggerFactory.getLogger(EAAFURICompare.class);
-
- private String serviceURL = "";
-
- /**
- *
- *
- * @param serviceURL public URL of the PVP S-Profile endpoint
- */
- public EAAFURICompare(String serviceURL) {
- this.serviceURL = serviceURL;
- }
-
- public boolean compare(String uri1, String uri2) {
- if (this.serviceURL.equals(uri1))
- return true;
-
- else {
- log.warn("PVP request destination-endpoint: " + uri1
- + " does not match to IDP endpoint:" + serviceURL);
- return false;
-
- }
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java
new file mode 100644
index 00000000..9015c40b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.validation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.net.URIComparator;
+
+public class EaafUriCompare implements URIComparator {
+ private static final Logger log = LoggerFactory.getLogger(EaafUriCompare.class);
+
+ private String serviceUrl = "";
+
+ /**
+ * SAML2 URL comperator.
+ *
+ * @param serviceUrl public URL of the PVP S-Profile endpoint
+ */
+ public EaafUriCompare(final String serviceUrl) {
+ this.serviceUrl = serviceUrl;
+ }
+
+ @Override
+ public boolean compare(final String uri1, final String uri2) {
+ if (this.serviceUrl.equals(uri1)) {
+ return true;
+ } else {
+ log.warn("PVP request destination-endpoint: " + uri1 + " does not match to IDP endpoint:"
+ + serviceUrl);
+ return false;
+
+ }
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java
index 18ee5797..f0758706 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java
@@ -1,65 +1,86 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.validation;
import java.util.ArrayList;
import java.util.List;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.MetadataCredentialResolver;
-import org.opensaml.xml.security.keyinfo.BasicProviderKeyInfoCredentialResolver;
-import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
-import org.opensaml.xml.security.keyinfo.KeyInfoProvider;
-import org.opensaml.xml.security.keyinfo.provider.DSAKeyValueProvider;
-import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider;
-import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;
+
+import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
+import org.opensaml.saml.security.impl.MetadataCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+@Slf4j
public class TrustEngineFactory {
- public static SignatureTrustEngine getSignatureKnownKeysTrustEngine(MetadataProvider provider) {
- MetadataCredentialResolver resolver;
+ /**
+ * Get OpenSAML2 TrustEngine.
+ *
+ * @param mdResolver Metadata provider
+ * @return TrustEngine for SAML2 message validation
+ * @throws Pvp2InternalErrorException In case of a TrustEngine initialization
+ * error
+ */
+ public static SignatureTrustEngine getSignatureKnownKeysTrustEngine(
+ final IPvp2MetadataProvider mdResolver) throws Pvp2InternalErrorException {
+ try {
+ final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>();
+ keyInfoProvider.add(new DSAKeyValueProvider());
+ keyInfoProvider.add(new RSAKeyValueProvider());
+ keyInfoProvider.add(new InlineX509DataProvider());
+ final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver(
+ keyInfoProvider);
+
+ final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver(
+ mdResolver);
+ roleDescriptorResolver.setRequireValidMetadata(true);
+ roleDescriptorResolver.initialize();
- resolver = new MetadataCredentialResolver(provider);
+ final MetadataCredentialResolver resolver = new MetadataCredentialResolver();
+ resolver.setRoleDescriptorResolver(roleDescriptorResolver);
+ resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver);
+ resolver.initialize();
- List<KeyInfoProvider> keyInfoProvider = new ArrayList<KeyInfoProvider>();
- keyInfoProvider.add(new DSAKeyValueProvider());
- keyInfoProvider.add(new RSAKeyValueProvider());
- keyInfoProvider.add(new InlineX509DataProvider());
+ final ExplicitKeySignatureTrustEngine engine =
+ new ExplicitKeySignatureTrustEngine(resolver, keyInfoCredentialResolver);
- KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver(
- keyInfoProvider);
+ return engine;
- ExplicitKeySignatureTrustEngine engine = new ExplicitKeySignatureTrustEngine(
- resolver, keyInfoResolver);
+ } catch (final ComponentInitializationException e) {
+ log.warn("Initialization of SignatureTrustEngine FAILED.", e);
+ throw new Pvp2InternalErrorException(e);
- return engine;
+ }
- }
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java
index 424c4431..c28dd7fb 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java
@@ -1,154 +1,151 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import javax.annotation.Nullable;
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public abstract class AbstractMetadataSignatureFilter implements MetadataFilter {
- private static final Logger log = LoggerFactory.getLogger(AbstractMetadataSignatureFilter.class);
-
- public void doFilter(XMLObject metadata) throws SignatureValidationException {
- try {
- if (metadata instanceof EntitiesDescriptor) {
- EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata;
- if(entitiesDescriptor.getSignature() == null) {
- throw new PVP2MetadataException("pvp2.26",
- new Object[] {"Root element of metadata file has to be signed"});
- }
- processEntitiesDescriptor(entitiesDescriptor);
-
-
- if (entitiesDescriptor.getEntityDescriptors().size() == 0) {
- throw new PVP2MetadataException("pvp2.26",
- new Object[] {"No valid entity in metadata " + entitiesDescriptor.getName()});
- }
-
-
- } else if (metadata instanceof EntityDescriptor) {
- EntityDescriptor entityDescriptor = (EntityDescriptor) metadata;
- processEntityDescriptorr(entityDescriptor);
-
- } else
- throw new PVP2MetadataException("pvp2.26",
- new Object[] {"Invalid Metadata file Root element is unknown"});
-
-
-
- log.info("Metadata signature policy check done OK");
- } catch (EAAFException e) {
- log.warn("Metadata signature policy check FAILED.", e);
- throw new SignatureValidationException(e);
-
- }
- }
-
- /**
- * Signature verification of a SAML2 EntityDescriptor element
- *
- * @param desc
- * @throws PVP2MetadataException if the signature is not valid or can not verified
- */
- protected abstract void verify(EntityDescriptor desc) throws PVP2MetadataException;
-
- /**
- * Signature verification of a SAML2 EntitiesDescriptor element
- *
- * @param desc
- * @throws PVP2MetadataException if the signature is not valid or can not verified
- */
- protected abstract void verify(EntitiesDescriptor desc) throws PVP2MetadataException;
-
- /**
- * Verify a EntityDescriptor element of an EntitiesDescriptor
- *
- * @param entity EntityDescriptor to verify
- * @param desc Full EntitiesDescriptor that contains the EntityDescriptor
- * @throws PVP2MetadataException
- */
- protected abstract void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws PVP2MetadataException;
-
-
- private void processEntityDescriptorr(EntityDescriptor desc) throws EAAFException {
- verify(desc);
-
- }
-
- private void processEntitiesDescriptor(EntitiesDescriptor desc) throws EAAFException {
- Iterator<EntitiesDescriptor> entID = desc.getEntitiesDescriptors().iterator();
-
- if(desc.getSignature() != null) {
- verify(desc);
-
- }
-
- while(entID.hasNext()) {
- processEntitiesDescriptor(entID.next());
- }
-
- Iterator<EntityDescriptor> entIT = desc.getEntityDescriptors().iterator();
- List<EntityDescriptor> verifiedEntIT = new ArrayList<EntityDescriptor>();
-
- //check every Entity
- while(entIT.hasNext()) {
- EntityDescriptor entity = entIT.next();
- log.debug("Validate metadata for entityID: " + entity.getEntityID() + " ..... ");
- try {
- verify(entity, desc);
-
- //add entity to verified entity-list
- verifiedEntIT.add(entity);
- log.debug("Metadata for entityID: " + entity.getEntityID() + " valid");
-
-
- } catch (Exception e) {
- //remove entity of signature can not be verified.
- log.info("Entity " + entity.getEntityID() + " is removed from metadata "
- + desc.getName() + ". Entity verification error: " + e.getMessage());
-
- }
-
- }
-
- //set only verified entity elements
- desc.getEntityDescriptors().clear();
- desc.getEntityDescriptors().addAll(verifiedEntIT);
- }
+ private static final Logger log = LoggerFactory.getLogger(AbstractMetadataSignatureFilter.class);
+
+ @Override
+ public XMLObject filter(@Nullable final XMLObject metadata) throws SignatureValidationException {
+ try {
+ if (metadata instanceof EntitiesDescriptor) {
+ final EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata;
+ if (entitiesDescriptor.getSignature() == null) {
+ throw new Pvp2MetadataException("pvp2.26",
+ new Object[] { "Root element of metadata file has to be signed" });
+ }
+ processEntitiesDescriptor(entitiesDescriptor);
+
+ if (entitiesDescriptor.getEntityDescriptors().size() == 0) {
+ throw new Pvp2MetadataException("pvp2.26",
+ new Object[] { "No valid entity in metadata " + entitiesDescriptor.getName() });
+ }
+
+ } else if (metadata instanceof EntityDescriptor) {
+ final EntityDescriptor entityDescriptor = (EntityDescriptor) metadata;
+ processEntityDescriptorr(entityDescriptor);
+
+ } else {
+ throw new Pvp2MetadataException("pvp2.26",
+ new Object[] { "Invalid Metadata file Root element is unknown" });
+ }
+
+ log.info("Metadata signature policy check done OK");
+ } catch (final EaafException e) {
+ log.warn("Metadata signature policy check FAILED.", e);
+ throw new SignatureValidationException(e);
+
+ }
+
+ return metadata;
+
+ }
+
+ /**
+ * Signature verification of a SAML2 EntityDescriptor element.
+ *
+ * @param desc EntityDescriptor
+ * @throws Pvp2MetadataException if the signature is not valid or can not
+ * verified
+ */
+ protected abstract void verify(EntityDescriptor desc) throws Pvp2MetadataException;
+
+ /**
+ * Signature verification of a SAML2 EntitiesDescriptor element.
+ *
+ * @param desc EntitiesDescriptor
+ * @throws Pvp2MetadataException if the signature is not valid or can not
+ * verified
+ */
+ protected abstract void verify(EntitiesDescriptor desc) throws Pvp2MetadataException;
+
+ /**
+ * Verify a EntityDescriptor element of an EntitiesDescriptor.
+ *
+ * @param entity EntityDescriptor to verify
+ * @param desc Full EntitiesDescriptor that contains the EntityDescriptor
+ * @throws Pvp2MetadataException In case of an verification error
+ */
+ protected abstract void verify(EntityDescriptor entity, EntitiesDescriptor desc)
+ throws Pvp2MetadataException;
+
+ private void processEntityDescriptorr(final EntityDescriptor desc) throws EaafException {
+ verify(desc);
+
+ }
+
+ private void processEntitiesDescriptor(final EntitiesDescriptor desc) throws EaafException {
+ final Iterator<EntitiesDescriptor> entID = desc.getEntitiesDescriptors().iterator();
+
+ if (desc.getSignature() != null) {
+ verify(desc);
+
+ }
+
+ while (entID.hasNext()) {
+ processEntitiesDescriptor(entID.next());
+ }
+
+ final Iterator<EntityDescriptor> entIT = desc.getEntityDescriptors().iterator();
+ final List<EntityDescriptor> verifiedEntIT = new ArrayList<>();
+
+ // check every Entity
+ while (entIT.hasNext()) {
+ final EntityDescriptor entity = entIT.next();
+ log.debug("Validate metadata for entityID: " + entity.getEntityID() + " ..... ");
+ try {
+ verify(entity, desc);
+
+ // add entity to verified entity-list
+ verifiedEntIT.add(entity);
+ log.debug("Metadata for entityID: " + entity.getEntityID() + " valid");
+
+ } catch (final Exception e) {
+ // remove entity of signature can not be verified.
+ log.info("Entity " + entity.getEntityID() + " is removed from metadata " + desc.getName()
+ + ". Entity verification error: " + e.getMessage());
+
+ }
+
+ }
+
+ // set only verified entity elements
+ desc.getEntityDescriptors().clear();
+ desc.getEntityDescriptors().addAll(verifiedEntIT);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java
deleted file mode 100644
index 87ab31fb..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.common.Extensions;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.metadata.AttributeConsumingService;
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.LocalizedString;
-import org.opensaml.saml2.metadata.RequestedAttribute;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.ServiceName;
-import org.opensaml.saml2.metadata.provider.FilterException;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.samlext.saml2mdattr.EntityAttributes;
-import org.opensaml.xml.XMLObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import at.gv.egiz.eaaf.core.impl.data.Trible;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
-
-/**
- * @author tlenz
- *
- */
-public class PVPEntityCategoryFilter implements MetadataFilter {
- private static final Logger log = LoggerFactory.getLogger(PVPEntityCategoryFilter.class);
-
- private boolean isUsed = false;
-
- /**
- * Filter to map PVP EntityCategories into a set of single PVP attributes
- *
- * @param isUsed if true PVP EntityCategories are mapped, otherwise they are ignored
- *
- */
- public PVPEntityCategoryFilter(boolean isUsed) {
- this.isUsed = isUsed;
- }
-
-
- /* (non-Javadoc)
- * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject)
- */
- @Override
- public void doFilter(XMLObject metadata) throws FilterException {
-
- if (isUsed) {
- log.trace("Map PVP EntityCategory to single PVP Attributes ... ");
- String entityId = null;
- try {
- if (metadata instanceof EntitiesDescriptor) {
- log.trace("Find EnitiesDescriptor ... ");
- EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata;
- if (entitiesDesc.getEntityDescriptors() != null) {
- for (EntityDescriptor el : entitiesDesc.getEntityDescriptors())
- resolveEntityCategoriesToAttributes(el);
-
- }
-
- } else if (metadata instanceof EntityDescriptor) {
- log.trace("Find EntityDescriptor");
- resolveEntityCategoriesToAttributes((EntityDescriptor)metadata);
-
-
- } else
- throw new PVP2MetadataException("pvp2.26",
- new Object[] {"Invalid Metadata file Root element is no Entities- or EntityDescriptor"});
-
-
-
- } catch (Exception e) {
- log.warn("SAML2 Metadata processing FAILED: Can not resolve EntityCategories for metadata: " + entityId, e);
-
- }
-
- } else
- log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated");
-
- }
-
- private void resolveEntityCategoriesToAttributes(EntityDescriptor metadata) {
- log.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ...");
- Extensions extensions = metadata.getExtensions();
- if (extensions != null) {
- List<XMLObject> listOfExt = extensions.getUnknownXMLObjects();
- if (listOfExt != null && !listOfExt.isEmpty()) {
- log.trace("Find #" + listOfExt.size() + " 'Extension' elements ");
- for (XMLObject el : listOfExt) {
- log.trace("Find ExtensionElement: " + el.getElementQName().toString());
- if (el instanceof EntityAttributes) {
- EntityAttributes entityAttrElem = (EntityAttributes)el;
- if (entityAttrElem.getAttributes() != null) {
- log.trace("Find EntityAttributes. Start attribute processing ...");
- for (Attribute entityAttr : entityAttrElem.getAttributes()) {
- if (entityAttr.getName().equals(PVPConstants.ENTITY_CATEGORY_ATTRIBITE)) {
- if (!entityAttr.getAttributeValues().isEmpty()) {
- String entityAttrValue = entityAttr.getAttributeValues().get(0).getDOM().getTextContent();
- if (PVPConstants.EGOVTOKEN.equals(entityAttrValue)) {
- log.debug("Find 'EGOVTOKEN' EntityAttribute. Adding single pvp attributes ... ");
- addAttributesToEntityDescriptor(metadata,
- buildAttributeList(PVPConstants.EGOVTOKEN_PVP_ATTRIBUTES),
- entityAttrValue);
-
-
- } else if (PVPConstants.CITIZENTOKEN.equals(entityAttrValue)) {
- log.debug("Find 'CITIZENTOKEN' EntityAttribute. Adding single pvp attributes ... ");
- addAttributesToEntityDescriptor(metadata,
- buildAttributeList(PVPConstants.CITIZENTOKEN_PVP_ATTRIBUTES),
- entityAttrValue);
-
- } else
- log.info("EntityAttributeValue: " + entityAttrValue + " is UNKNOWN!");
-
- } else
- log.info("EntityAttribute: No attribute value");
-
- } else
- log.info("EntityAttribute: " + entityAttr.getName() + " is NOT supported");
-
- }
-
- } else
- log.info("Can NOT resolve EntityAttributes! Reason: Only EntityAttributes are supported!");
-
- }
- }
-
- } else
- log.trace("'Extension' element is 'null' or empty");
-
- } else
- log.trace("No 'Extension' element found");
-
- }
-
- /**
- * @param metadata
- * @param attrList
- */
- private void addAttributesToEntityDescriptor(EntityDescriptor metadata, List<RequestedAttribute> attrList, String entityAttr) {
- SPSSODescriptor spSSODesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
- if (spSSODesc != null) {
- if (spSSODesc.getAttributeConsumingServices() == null ||
- spSSODesc.getAttributeConsumingServices().isEmpty()) {
- log.trace("No 'AttributeConsumingServices' found. Added it ...");
-
- AttributeConsumingService attributeService = SAML2Utils.createSAMLObject(AttributeConsumingService.class);
- attributeService.setIndex(0);
- attributeService.setIsDefault(true);
- ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class);
- serviceName.setName(new LocalizedString("Default Service", "en"));
- attributeService.getNames().add(serviceName);
-
- if (attrList != null && !attrList.isEmpty()) {
- attributeService.getRequestAttributes().addAll(attrList);
- log.info("Add " + attrList.size() + " attributes for 'EntityAttribute': " + entityAttr);
-
- }
-
- spSSODesc.getAttributeConsumingServices().add(attributeService);
-
- } else {
- log.debug("Find 'AttributeConsumingServices'. Starting updating process ... ");
- for (AttributeConsumingService el : spSSODesc.getAttributeConsumingServices()) {
- log.debug("Update 'AttributeConsumingService' with Index: " + el.getIndex());
-
- //load currently requested attributes
- List<String> currentlyReqAttr = new ArrayList<String>();
- for (RequestedAttribute reqAttr : el.getRequestAttributes())
- currentlyReqAttr.add(reqAttr.getName());
-
-
- //check against EntityAttribute List
- for (RequestedAttribute entityAttrListEl : attrList) {
- if (!currentlyReqAttr.contains(entityAttrListEl.getName())) {
- el.getRequestAttributes().add(entityAttrListEl);
-
- } else
- log.debug("'AttributeConsumingService' already contains attr: " + entityAttrListEl.getName());
-
- }
-
- }
-
- }
-
- } else
- log.info("Can ONLY add 'EntityAttributes' to 'SPSSODescriptor'");
-
- }
-
- private List<RequestedAttribute> buildAttributeList(List<Trible<String, String, Boolean>> attrSet) {
- List<RequestedAttribute> requestedAttributes = new ArrayList<RequestedAttribute>();
- for (Trible<String, String, Boolean> el : attrSet)
- requestedAttributes.add(PVPAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird()));
-
- return requestedAttributes;
-
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java
new file mode 100644
index 00000000..efbeb7e5
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.ext.saml2mdattr.EntityAttributes;
+import org.opensaml.saml.metadata.resolver.filter.FilterException;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.Extensions;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.saml2.metadata.ServiceName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Metadata filter that inject requested attributes based on Metadata
+ * EntityCategories.
+ *
+ * @author tlenz
+ *
+ */
+public class PvpEntityCategoryFilter implements MetadataFilter {
+ private static final Logger log = LoggerFactory.getLogger(PvpEntityCategoryFilter.class);
+
+ private boolean isUsed = false;
+
+ /**
+ * Filter to map PVP EntityCategories into a set of single PVP attributes.
+ *
+ * @param isUsed if true PVP EntityCategories are mapped, otherwise they are
+ * ignored
+ *
+ */
+ public PvpEntityCategoryFilter(final boolean isUsed) {
+ this.isUsed = isUsed;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml
+ * .XMLObject)
+ */
+ @Override
+ public XMLObject filter(final XMLObject metadata) throws FilterException {
+
+ if (isUsed) {
+ log.trace("Map PVP EntityCategory to single PVP Attributes ... ");
+ final String entityId = null;
+ try {
+ if (metadata instanceof EntitiesDescriptor) {
+ log.trace("Find EnitiesDescriptor ... ");
+ final EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata;
+ if (entitiesDesc.getEntityDescriptors() != null) {
+ for (final EntityDescriptor el : entitiesDesc.getEntityDescriptors()) {
+ resolveEntityCategoriesToAttributes(el);
+ }
+
+ }
+
+ } else if (metadata instanceof EntityDescriptor) {
+ log.trace("Find EntityDescriptor");
+ resolveEntityCategoriesToAttributes((EntityDescriptor) metadata);
+
+ } else {
+ throw new Pvp2MetadataException("pvp2.26", new Object[] {
+ "Invalid Metadata file Root element is no Entities- or EntityDescriptor" });
+ }
+
+ } catch (final Exception e) {
+ log.warn("SAML2 Metadata processing FAILED: Can not resolve EntityCategories for metadata: "
+ + entityId, e);
+
+ }
+
+ } else {
+ log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated");
+
+ }
+
+ return metadata;
+
+ }
+
+ private void resolveEntityCategoriesToAttributes(final EntityDescriptor metadata) {
+ log.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ...");
+ final Extensions extensions = metadata.getExtensions();
+ if (extensions != null) {
+ final List<XMLObject> listOfExt = extensions.getUnknownXMLObjects();
+ if (listOfExt != null && !listOfExt.isEmpty()) {
+ log.trace("Find #" + listOfExt.size() + " 'Extension' elements ");
+ for (final XMLObject el : listOfExt) {
+ log.trace("Find ExtensionElement: " + el.getElementQName().toString());
+ if (el instanceof EntityAttributes) {
+ final EntityAttributes entityAttrElem = (EntityAttributes) el;
+ if (entityAttrElem.getAttributes() != null) {
+ log.trace("Find EntityAttributes. Start attribute processing ...");
+ for (final Attribute entityAttr : entityAttrElem.getAttributes()) {
+ if (entityAttr.getName().equals(PvpConstants.ENTITY_CATEGORY_ATTRIBITE)) {
+ if (!entityAttr.getAttributeValues().isEmpty()) {
+ final String entityAttrValue =
+ entityAttr.getAttributeValues().get(0).getDOM().getTextContent();
+ if (PvpConstants.EGOVTOKEN.equals(entityAttrValue)) {
+ log.debug(
+ "Find 'EGOVTOKEN' EntityAttribute. Adding single pvp attributes ... ");
+ addAttributesToEntityDescriptor(metadata,
+ buildAttributeList(PvpConstants.EGOVTOKEN_PVP_ATTRIBUTES),
+ entityAttrValue);
+
+ } else if (PvpConstants.CITIZENTOKEN.equals(entityAttrValue)) {
+ log.debug(
+ "Find 'CITIZENTOKEN' EntityAttribute. Adding single pvp attributes ... ");
+ addAttributesToEntityDescriptor(metadata,
+ buildAttributeList(PvpConstants.CITIZENTOKEN_PVP_ATTRIBUTES),
+ entityAttrValue);
+
+ } else {
+ log.info("EntityAttributeValue: " + entityAttrValue + " is UNKNOWN!");
+ }
+
+ } else {
+ log.info("EntityAttribute: No attribute value");
+ }
+
+ } else {
+ log.info("EntityAttribute: " + entityAttr.getName() + " is NOT supported");
+ }
+
+ }
+
+ } else {
+ log.info(
+ "Can NOT resolve EntityAttributes! Reason: Only EntityAttributes are supported!");
+ }
+
+ }
+ }
+
+ } else {
+ log.trace("'Extension' element is 'null' or empty");
+ }
+
+ } else {
+ log.trace("No 'Extension' element found");
+ }
+
+ }
+
+ private void addAttributesToEntityDescriptor(final EntityDescriptor metadata,
+ final List<RequestedAttribute> attrList, final String entityAttr) {
+ final SPSSODescriptor spSsoDesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+ if (spSsoDesc != null) {
+ if (spSsoDesc.getAttributeConsumingServices() == null
+ || spSsoDesc.getAttributeConsumingServices().isEmpty()) {
+ log.trace("No 'AttributeConsumingServices' found. Added it ...");
+
+ final AttributeConsumingService attributeService =
+ Saml2Utils.createSamlObject(AttributeConsumingService.class);
+ attributeService.setIndex(0);
+ attributeService.setIsDefault(true);
+ final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class);
+ serviceName.setValue("Default Service");
+ serviceName.setXMLLang("en");
+ attributeService.getNames().add(serviceName);
+
+ if (attrList != null && !attrList.isEmpty()) {
+ attributeService.getRequestAttributes().addAll(attrList);
+ log.info("Add " + attrList.size() + " attributes for 'EntityAttribute': " + entityAttr);
+
+ }
+
+ spSsoDesc.getAttributeConsumingServices().add(attributeService);
+
+ } else {
+ log.debug("Find 'AttributeConsumingServices'. Starting updating process ... ");
+ for (final AttributeConsumingService el : spSsoDesc.getAttributeConsumingServices()) {
+ log.debug("Update 'AttributeConsumingService' with Index: " + el.getIndex());
+
+ // load currently requested attributes
+ final List<String> currentlyReqAttr = new ArrayList<>();
+ for (final RequestedAttribute reqAttr : el.getRequestAttributes()) {
+ currentlyReqAttr.add(reqAttr.getName());
+ }
+
+ // check against EntityAttribute List
+ for (final RequestedAttribute entityAttrListEl : attrList) {
+ if (!currentlyReqAttr.contains(entityAttrListEl.getName())) {
+ el.getRequestAttributes().add(entityAttrListEl);
+
+ } else {
+ log.debug("'AttributeConsumingService' already contains attr: "
+ + entityAttrListEl.getName());
+ }
+
+ }
+
+ }
+
+ }
+
+ } else {
+ log.info("Can ONLY add 'EntityAttributes' to 'SPSSODescriptor'");
+ }
+
+ }
+
+ private List<RequestedAttribute> buildAttributeList(
+ final List<Triple<String, String, Boolean>> attrSet) {
+ final List<RequestedAttribute> requestedAttributes = new ArrayList<>();
+ for (final Triple<String, String, Boolean> el : attrSet) {
+ requestedAttributes
+ .add(PvpAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird()));
+ }
+
+ return requestedAttributes;
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java
index b5de4b21..b9e0c37f 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java
@@ -1,106 +1,96 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml2.metadata.provider.FilterException;
-import org.opensaml.saml2.metadata.provider.MetadataFilter;
-import org.opensaml.xml.XMLObject;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version;
+import org.opensaml.saml.metadata.resolver.filter.FilterException;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
-
-/**
- * @author tlenz
- *
- */
public class SchemaValidationFilter implements MetadataFilter {
- private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class);
- private boolean isActive = true;
-
- public SchemaValidationFilter() {
- }
-
- /**
- *
- */
- public SchemaValidationFilter(boolean useSchemaValidation) {
- this.isActive = useSchemaValidation;
- }
-
-
- /* (non-Javadoc)
- * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject)
- */
- @Override
- public void doFilter(XMLObject arg0) throws FilterException {
-
- String errString = null;
-
- if (isActive) {
- try {
- Schema test = SAMLSchemaBuilder.getSAML11Schema();
- Validator val = test.newValidator();
- DOMSource source = new DOMSource(arg0.getDOM());
- val.validate(source);
- log.info("Metadata Schema validation check done OK");
- return;
-
- } catch (SAXException e) {
- if (log.isDebugEnabled() || log.isTraceEnabled())
- log.warn("Metadata Schema validation FAILED with exception:", e);
- else
- log.warn("Metadata Schema validation FAILED with message: "+ e.getMessage());
-
- errString = e.getMessage();
-
- } catch (Exception e) {
- if (log.isDebugEnabled() || log.isTraceEnabled())
- log.warn("Metadata Schema validation FAILED with exception:", e);
- else
- log.warn("Metadata Schema validation FAILED with message: "+ e.getMessage());
-
- errString = e.getMessage();
-
- }
-
- throw new FilterException(
- new SchemaValidationException("pvp2.26",
- new Object[] {"Metadata Schema validation FAILED with message: " + errString}));
-
- } else
- log.info("Metadata Schema validation check is DEACTIVATED!");
-
- }
+ private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class);
+ private boolean isActive = true;
+
+ private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);
+
+ /**
+ * XML Schema validation filter for SAML2 metadata.
+ * <p>Schemavalidation is active by default</p>
+ */
+ public SchemaValidationFilter() {
+
+ }
+
+ /**
+ * XML Schema validation filter for SAML2 metadata.
+ *
+ * @param useSchemaValidation <code>true</code> XML schema validation is active, otherwise <code>false</code>
+ */
+ public SchemaValidationFilter(final boolean useSchemaValidation) {
+ this.isActive = useSchemaValidation;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml
+ * .XMLObject)
+ */
+ @Override
+ public XMLObject filter(final XMLObject arg0) throws FilterException {
+
+ if (isActive) {
+ try {
+ final Schema test = schemaBuilder.getSAMLSchema();
+ final Validator val = test.newValidator();
+ final DOMSource source = new DOMSource(arg0.getDOM());
+ val.validate(source);
+ log.info("Metadata Schema validation check done OK");
+
+ } catch (final Exception e) {
+ if (log.isDebugEnabled() || log.isTraceEnabled()) {
+ log.warn("Metadata Schema validation FAILED with exception:", e);
+ } else {
+ log.warn("Metadata Schema validation FAILED with message: " + e.getMessage());
+ }
+
+ throw new FilterException(new SchemaValidationException("internal.pvp.03",
+ new Object[] { e.getMessage() }, e));
+ }
+
+ } else {
+ log.info("Metadata Schema validation check is DEACTIVATED!");
+
+ }
+
+ return arg0;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java
new file mode 100644
index 00000000..ef09e5c4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2018 A-SIT Plus GmbH
+ * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ,
+ * A-SIT Plus GmbH, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "License");
+ * You may not use this work except in compliance with the License.
+ * You may obtain a copy of the License at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMetadataSignatureException;
+
+import org.opensaml.saml.common.SignableSAMLObject;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.SignatureValidator;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SimpleMetadataSignatureVerificationFilter extends AbstractMetadataSignatureFilter {
+
+ private final String metadataUrl;
+ private final List<BasicX509Credential> trustedCredential = new ArrayList<>();
+
+ private static final String ERROR_07 = "internal.pvp.07";
+ private static final String ERROR_12 = "internal.pvp.12";
+ private static final String ERROR_MSG_ENTITIESDESC = "EntitiesDescritors are NOT supported";
+ private static final String ERROR_MSG_SIGNOTVALID = "Signature not valid or no trusted certificate found";
+
+ /**
+ * SAML2 metadata-signature verification-filter that uses a simple {@link List}
+ * of trusted {@link BasicX509Credential} as truststore. <br>
+ * <p>
+ * This filter only validates {@link EntityDescriptor} elements.<br>
+ * SAML2 metadata with {@link EntitiesDescriptor} <b>are not supported.</b>
+ * </p>
+ *
+ * @param credentials Trust X509 certificates
+ * @param metadataUrl Metadata URL for logging purposes
+ */
+ public SimpleMetadataSignatureVerificationFilter(@Nonnull List<BasicX509Credential> credentials,
+ @Nonnull String metadataUrl) {
+ this.metadataUrl = metadataUrl;
+ this.trustedCredential.addAll(credentials);
+
+ }
+
+ @Override
+ protected void verify(EntityDescriptor desc) throws Pvp2MetadataException {
+ try {
+ internalVerify(desc);
+
+ } catch (final EaafException e) {
+ log.info("Metadata verification FAILED for: {} Reason: {}", metadataUrl, e.getMessage());
+ throw new Pvp2MetadataException(ERROR_07,
+ new Object[] { metadataUrl, e.getMessage() }, e);
+
+ }
+ }
+
+ @Override
+ protected void verify(EntitiesDescriptor desc) throws Pvp2MetadataException {
+ throw new Pvp2MetadataException(ERROR_07,
+ new Object[] { metadataUrl, ERROR_MSG_ENTITIESDESC });
+
+ }
+
+ @Override
+ protected void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws Pvp2MetadataException {
+ throw new Pvp2MetadataException(ERROR_07,
+ new Object[] { metadataUrl, ERROR_MSG_ENTITIESDESC });
+
+ }
+
+ private void internalVerify(SignableSAMLObject signedElement)
+ throws EaafException {
+ // check if signature exists
+ if (signedElement.getSignature() == null) {
+ throw new Pvp2MetadataException(ERROR_12,
+ new Object[] { metadataUrl });
+
+ }
+
+ // perform general signature validation
+ try {
+ final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator();
+ sigValidator.validate(signedElement.getSignature());
+
+ } catch (final SignatureException e) {
+ log.error("Failed to validate Signature", e);
+ throw new Pvp2MetadataException(ERROR_07,
+ new Object[] { metadataUrl, e.getMessage() }, e);
+
+ }
+
+ // perform cryptographic signature verification
+ boolean isTrusted = false;
+ for (final BasicX509Credential cred : trustedCredential) {
+ log.trace("Validating signature with credential: {} ... ",
+ cred.getEntityCertificate().getSubjectDN());
+ try {
+ SignatureValidator.validate(signedElement.getSignature(), cred);
+ isTrusted = true;
+
+ } catch (final SignatureException e) {
+ log.debug("Failed to verfiy Signature with cert: {} Reason: {}",
+ cred.getEntityCertificate().getSubjectDN(), e.getMessage());
+
+ }
+ }
+
+ if (!isTrusted) {
+ log.info("PVP2 metadata: " + metadataUrl + " are NOT trusted!");
+ throw new SamlMetadataSignatureException(metadataUrl, ERROR_MSG_SIGNOTVALID);
+
+ }
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
deleted file mode 100644
index f1dd1269..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
-
-import javax.xml.namespace.QName;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.Validator;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.SignableSAMLObject;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.security.MetadataCriteria;
-import org.opensaml.security.SAMLSignatureProfileValidator;
-import org.opensaml.ws.message.MessageContext;
-import org.opensaml.ws.security.SecurityPolicyException;
-import org.opensaml.ws.security.SecurityPolicyRule;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.security.CriteriaSet;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.criteria.EntityIDCriteria;
-import org.opensaml.xml.security.criteria.UsageCriteria;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.validation.ValidationException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
-
-/**
- * @author tlenz
- *
- */
-public abstract class AbstractRequestSignedSecurityPolicyRule implements SecurityPolicyRule {
-
- private static final Logger log = LoggerFactory.getLogger(AbstractRequestSignedSecurityPolicyRule.class);
-
-
- private SignatureTrustEngine trustEngine = null;
- private QName peerEntityRole = null;
- /**
- * @param peerEntityRole
- *
- */
- public AbstractRequestSignedSecurityPolicyRule(SignatureTrustEngine trustEngine, QName peerEntityRole) {
- this.trustEngine = trustEngine;
- this.peerEntityRole = peerEntityRole;
-
- }
-
-
- /**
- * Reload the PVP metadata for a given entity
- *
- * @param entityID for which the metadata should be refreshed.
- * @return true if the refresh was successful, otherwise false
- */
- protected abstract boolean refreshMetadataProvider(String entityID);
-
-
- protected abstract SignableSAMLObject getSignedSAMLObject(XMLObject inboundData);
-
- /* (non-Javadoc)
- * @see org.opensaml.ws.security.SecurityPolicyRule#evaluate(org.opensaml.ws.message.MessageContext)
- */
- @Override
- public void evaluate(MessageContext context) throws SecurityPolicyException {
- try {
- verifySignature(context);
-
- } catch (SecurityPolicyException e) {
- if (StringUtils.isEmpty(context.getInboundMessageIssuer())) {
- throw e;
-
- }
- log.debug("PVP2X message validation FAILED. Reload metadata for entityID: " + context.getInboundMessageIssuer());
- if (!refreshMetadataProvider(context.getInboundMessageIssuer()))
- throw e;
-
- else {
- log.trace("PVP2X metadata reload finished. Check validate message again.");
- verifySignature(context);
-
- }
- log.trace("Second PVP2X message validation finished");
-
- }
-
-
- }
-
- private void verifySignature(MessageContext context) throws SecurityPolicyException {
- SignableSAMLObject samlObj = getSignedSAMLObject(context.getInboundMessage());
- if (samlObj != null && samlObj.getSignature() != null) {
-
- SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
- try {
- profileValidator.validate(samlObj.getSignature());
- performSchemaValidation(samlObj.getDOM());
-
- } catch (ValidationException e) {
- log.warn("Signature is not conform to SAML signature profile", e);
- throw new SecurityPolicyException("Signature is not conform to SAML signature profile");
-
- } catch (SchemaValidationException e) {
- log.warn("Signature is not conform to SAML signature profile", e);
- throw new SecurityPolicyException("Signature is not conform to SAML signature profile");
-
- }
-
-
-
- CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add( new EntityIDCriteria(context.getInboundMessageIssuer()) );
- criteriaSet.add( new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS) );
- criteriaSet.add( new UsageCriteria(UsageType.SIGNING) );
-
- try {
- if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) {
- throw new SecurityPolicyException("Signature validation FAILED.");
-
- }
- log.debug("PVP message signature valid.");
-
- } catch (org.opensaml.xml.security.SecurityException e) {
- log.info("PVP2x message signature validation FAILED. Message:" + e.getMessage());
- throw new SecurityPolicyException("Signature validation FAILED.");
-
- }
-
- } else {
- throw new SecurityPolicyException("PVP Message is not signed.");
-
- }
-
- }
-
- private void performSchemaValidation(Element source) throws SchemaValidationException {
-
- String err = null;
- try {
- Schema test = SAMLSchemaBuilder.getSAML11Schema();
- Validator val = test.newValidator();
- val.validate(new DOMSource(source));
- log.debug("Schema validation check done OK");
- return;
-
- } catch (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 (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("pvp2.22", new Object[]{err});
-
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java
new file mode 100644
index 00000000..aba0a68b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java
@@ -0,0 +1,64 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import javax.annotation.Nonnull;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
+
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+import org.opensaml.xmlsec.SignatureValidationParameters;
+import org.opensaml.xmlsec.context.SecurityParametersContext;
+import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+@Slf4j
+public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> {
+
+ private final IPvp2MetadataProvider internalMetadataProvider;
+ private SignatureTrustEngine trustEngine;
+
+ public EaafMessageContextInitializationHandler(@Nonnull IPvp2MetadataProvider metadataProvider) {
+ internalMetadataProvider = metadataProvider;
+ }
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ try {
+ trustEngine = TrustEngineFactory.getSignatureKnownKeysTrustEngine(internalMetadataProvider);
+
+ } catch (final Pvp2InternalErrorException e) {
+ throw new ComponentInitializationException("TrustEngine injection FAILED", e);
+
+ }
+ }
+
+
+ @Override
+ protected void doInvoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException {
+ log.trace("Injecting sub-context to SAML2 message ... ");
+ messageContext.addSubcontext(new SAMLPeerEntityContext());
+ messageContext.addSubcontext(new SAMLMessageInfoContext());
+
+
+ final SecurityParametersContext securityParameterContext = new SecurityParametersContext();
+ final SignatureValidationParameters sigValParameters = new SignatureValidationParameters();
+ securityParameterContext.setSignatureValidationParameters(sigValParameters);
+ messageContext.addSubcontext(securityParameterContext);
+
+ sigValParameters.setBlacklistedAlgorithms(
+ ConfigurationService.get(SignatureValidationConfiguration.class)
+ .getBlacklistedAlgorithms());
+ sigValParameters.setSignatureTrustEngine(trustEngine);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java
new file mode 100644
index 00000000..204229ee
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java
@@ -0,0 +1,107 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.codec.Base64Support;
+
+/**
+ * Always extracts the last http parameter with a specific name from request, if
+ * more than one with the same name exists.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class EaafSaml2HttpRedirectDeflateSignatureSecurityHandler extends
+ SAML2HTTPRedirectDeflateSignatureSecurityHandler {
+
+ public static final String HTTP_REDIRECT_SIGALG = "SigAlg";
+ public static final String HTTP_REDIRECT_SIGNATURE = "Signature";
+
+ private IRefreshableMetadataProvider refreshableMetadataProvider = null;
+
+ /**
+ * Signature verification handler that reloads SAML2 metadata if signature
+ * verification fails.
+ *
+ * @param metadataProvider Metadata provider implementation. Refreshing is only
+ * possible, if that provider implements
+ * {@link IRefreshableMetadataProvider}
+ */
+ public EaafSaml2HttpRedirectDeflateSignatureSecurityHandler(
+ @Nullable IPvp2MetadataProvider metadataProvider) {
+ if (metadataProvider != null) {
+ if (metadataProvider instanceof IRefreshableMetadataProvider) {
+ refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider;
+
+ } else {
+ log.trace("Refreshing is not supported by {} metadata-provider",
+ metadataProvider.getClass().getSimpleName());
+
+ }
+ }
+ }
+
+ @Override
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+ try {
+ super.doInvoke(messageContext);
+
+ } catch (final MessageHandlerException e) {
+ if (refreshableMetadataProvider != null) {
+
+ log.debug("Starting metadata refresh process ... ");
+ if (refreshableMetadataProvider.refreshMetadataProvider(
+ messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) {
+ log.trace("Refreshing successful. Restarting message evaluation ... ");
+
+ try {
+ super.doInvoke(messageContext);
+ return;
+
+ } catch (final MessageHandlerException e1) {
+ log.debug("Signature validation fails twice with second error: {}", e.getMessage());
+
+ }
+ }
+ }
+
+ log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage());
+ throw new MessageHandlerException(
+ new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e));
+ }
+ }
+
+ @Override
+ @Nullable
+ protected byte[] getSignature() throws MessageHandlerException {
+ final String signature = SamlHttpUtils.getLastParameterFromRequest(
+ getHttpServletRequest(), HTTP_REDIRECT_SIGNATURE);
+
+ if (Strings.isNullOrEmpty(signature)) {
+ return null;
+
+ }
+ return Base64Support.decode(signature);
+ }
+
+ @Override
+ @Nullable
+ protected String getSignatureAlgorithm() throws MessageHandlerException {
+ return SamlHttpUtils.getLastParameterFromRequest(getHttpServletRequest(), HTTP_REDIRECT_SIGALG);
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java
new file mode 100644
index 00000000..9f6bc864
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java
@@ -0,0 +1,75 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EaafSamlProtocolMessageXmlSignatureSecurityHandler extends
+ SAMLProtocolMessageXMLSignatureSecurityHandler {
+
+ private IRefreshableMetadataProvider refreshableMetadataProvider = null;
+
+ /**
+ * Signature verification handler that reloads SAML2 metadata if signature
+ * verification fails.
+ *
+ * @param metadataProvider Metadata provider implementation. Refreshing is only
+ * possible, if that provider implements
+ * {@link IRefreshableMetadataProvider}
+ */
+ public EaafSamlProtocolMessageXmlSignatureSecurityHandler(
+ @Nullable IPvp2MetadataProvider metadataProvider) {
+ if (metadataProvider != null) {
+ if (metadataProvider instanceof IRefreshableMetadataProvider) {
+ refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider;
+
+ } else {
+ log.trace("Refreshing is not supported by {} metadata-provider",
+ metadataProvider.getClass().getSimpleName());
+
+ }
+ }
+ }
+
+ @Override
+ public void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
+ try {
+ super.doInvoke(messageContext);
+
+ } catch (final MessageHandlerException e) {
+ if (refreshableMetadataProvider != null) {
+
+ log.debug("Starting metadata refresh process ... ");
+ if (refreshableMetadataProvider.refreshMetadataProvider(
+ messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) {
+ log.trace("Refreshing successful. Restarting message evaluation ... ");
+
+ try {
+ super.doInvoke(messageContext);
+ return;
+
+ } catch (final MessageHandlerException e1) {
+ log.debug("Signature validation fails twice with second error: {}", e.getMessage());
+
+ }
+ }
+ }
+
+ log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage());
+ throw new MessageHandlerException(
+ new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e));
+ }
+
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java
deleted file mode 100644
index 6d5fdff8..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
-
-import java.util.List;
-
-import org.opensaml.common.binding.SAMLMessageContext;
-import org.opensaml.saml2.binding.security.SAML2AuthnRequestsSignedRule;
-import org.opensaml.ws.transport.http.HTTPInTransport;
-import org.opensaml.xml.util.DatatypeHelper;
-
-/**
- * @author tlenz
- *
- */
-public class PVPAuthRequestSignedRole extends SAML2AuthnRequestsSignedRule {
-
- @Override
- protected boolean isMessageSigned(SAMLMessageContext messageContext) {
- // This handles HTTP-Redirect and HTTP-POST-SimpleSign bindings.
- HTTPInTransport inTransport = (HTTPInTransport) messageContext.getInboundMessageTransport();
-
- //Check signature parameter exists only once and is not empty
- List<String> sigParam = inTransport.getParameterValues("Signature");
- boolean isValidSigned = sigParam.size() == 1 && !DatatypeHelper.isEmpty(sigParam.get(0));
-
- //Check signature-algorithm parameter exists only once and is not empty
- List<String> sigAlgParam = inTransport.getParameterValues("SigAlg");
- boolean isValidSigAlgExists = sigAlgParam.size() == 1 && !DatatypeHelper.isEmpty(sigAlgParam.get(0));
-
- //Check signature-content parameter exists only once and is not empty
- List<String> samlReqParam = inTransport.getParameterValues("SAMLRequest");
- List<String> samlRespParam = inTransport.getParameterValues("SAMLResponse");
- boolean isValidContent = ( ( samlReqParam.size() == 1 && !DatatypeHelper.isEmpty(samlReqParam.get(0)) )
- || ( samlRespParam.size() == 1 && !DatatypeHelper.isEmpty(samlRespParam.get(0)) )
- ) && !(samlReqParam.size() == 1 && samlRespParam.size() == 1)
- ;
-
- return isValidSigned && isValidSigAlgExists && isValidContent;
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java
deleted file mode 100644
index eecaf4f0..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
-
-import javax.xml.namespace.QName;
-
-import org.opensaml.common.SignableSAMLObject;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
-
-/**
- * @author tlenz
- *
- */
-public class PVPSignedRequestPolicyRule extends
- AbstractRequestSignedSecurityPolicyRule {
-
- private IRefreshableMetadataProvider metadataProvider = null;
-
- /**
- * @param metadataProvider
- * @param trustEngine
- * @param peerEntityRole
- */
- public PVPSignedRequestPolicyRule(MetadataProvider metadataProvider, SignatureTrustEngine trustEngine,
- QName peerEntityRole) {
- super(trustEngine, peerEntityRole);
- if (metadataProvider instanceof IRefreshableMetadataProvider)
- this.metadataProvider = (IRefreshableMetadataProvider) metadataProvider;
-
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#refreshMetadataProvider(java.lang.String)
- */
- @Override
- protected boolean refreshMetadataProvider(String entityID) {
- if (metadataProvider != null)
- return metadataProvider.refreshMetadataProvider(entityID);
-
- return false;
-
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#getSignedSAMLObject(org.opensaml.xml.XMLObject)
- */
- @Override
- protected SignableSAMLObject getSignedSAMLObject(XMLObject inboundData) {
- if (inboundData instanceof SignableSAMLObject)
- return (SignableSAMLObject) inboundData;
-
- else
- return null;
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java
new file mode 100644
index 00000000..a1365023
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java
@@ -0,0 +1,71 @@
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerChain;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.opensaml.saml.common.SAMLObject;
+
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+@Slf4j
+public class PvpSamlMessageHandlerChain implements MessageHandlerChain<SAMLObject> {
+ private final List<MessageHandler<SAMLObject>> handlers = new ArrayList<>();
+ private boolean isInitialized = false;
+
+ @Override
+ public void invoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException {
+ if (!isInitialized) {
+ throw new RuntimeException("Component: "
+ + PvpSamlMessageHandlerChain.class.getName() + " not initialized");
+
+ }
+
+ for (final MessageHandler<SAMLObject> handler : getHandlers()) {
+ log.trace("Initializing SAML message handler: {}", handler.getClass().getName());
+ handler.invoke(messageContext);
+
+ }
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isInitialized;
+
+ }
+
+ @Override
+ public void initialize() throws ComponentInitializationException {
+ if (!isInitialized) {
+ for (final MessageHandler<SAMLObject> handler : getHandlers()) {
+ log.trace("Initializing SAML message handler: {}", handler.getClass().getName());
+ handler.initialize();
+
+ }
+
+ isInitialized = true;
+ }
+
+ }
+
+ @Override
+ public List<MessageHandler<SAMLObject>> getHandlers() {
+ return handlers;
+
+ }
+
+ public void addHandler(MessageHandler<SAMLObject> handler) {
+ handlers.add(handler);
+
+ }
+
+ public void addHandlers(List<MessageHandler<SAMLObject>> handlerList) {
+ handlers.addAll(handlerList);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java
deleted file mode 100644
index 078e4ac0..00000000
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
-
-import javax.xml.namespace.QName;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.Validator;
-
-import org.apache.commons.lang3.StringUtils;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.common.xml.SAMLSchemaBuilder;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.saml2.metadata.IDPSSODescriptor;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.security.MetadataCriteria;
-import org.opensaml.security.SAMLSignatureProfileValidator;
-import org.opensaml.xml.security.CriteriaSet;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.criteria.EntityIDCriteria;
-import org.opensaml.xml.security.criteria.UsageCriteria;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.validation.ValidationException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider;
-import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse;
-
-@Service("SAMLVerificationEngine")
-public class SAMLVerificationEngine {
- private static final Logger log = LoggerFactory.getLogger(SAMLVerificationEngine.class);
-
-
- @Autowired(required=true) IPVPMetadataProvider metadataProvider;
-
- public void verify(InboundMessage msg, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {
- try {
- if (msg instanceof PVPSProfileRequest &&
- ((PVPSProfileRequest)msg).getSamlRequest() instanceof RequestAbstractType)
- verifyRequest(((RequestAbstractType)((PVPSProfileRequest)msg).getSamlRequest()), sigTrustEngine);
-
- else
- verifyIDPResponse(((PVPSProfileResponse)msg).getResponse(), sigTrustEngine);
-
- } catch (InvalidProtocolRequestException e) {
- if (StringUtils.isEmpty(msg.getEntityID())) {
- throw e;
-
- }
- 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.");
-
- if (msg instanceof PVPSProfileRequest &&
- ((PVPSProfileRequest)msg).getSamlRequest() instanceof RequestAbstractType)
- verifyRequest(((RequestAbstractType)((PVPSProfileRequest)msg).getSamlRequest()), sigTrustEngine);
-
- else
- verifyIDPResponse(((PVPSProfileResponse)msg).getResponse(), sigTrustEngine);
-
- }
- log.trace("Second PVP2X message validation finished");
- }
- }
-
- public void verifySLOResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException {
- verifyResponse(samlObj, sigTrustEngine, SPSSODescriptor.DEFAULT_ELEMENT_NAME);
-
- }
-
- public void verifyIDPResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException{
- verifyResponse(samlObj, sigTrustEngine, IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
-
- }
-
- private void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine, QName defaultElementName) throws InvalidProtocolRequestException{
- SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
- try {
- profileValidator.validate(samlObj.getSignature());
- performSchemaValidation(samlObj.getDOM());
-
- } catch (ValidationException e) {
- log.warn("Signature is not conform to SAML signature profile", e);
- throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
-
- } catch (SchemaValidationException e) {
- throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
-
- }
-
- CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add( new EntityIDCriteria(samlObj.getIssuer().getValue()) );
- criteriaSet.add( new MetadataCriteria(defaultElementName, SAMLConstants.SAML20P_NS) );
- criteriaSet.add( new UsageCriteria(UsageType.SIGNING) );
-
- try {
- if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) {
- throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
- }
- } catch (org.opensaml.xml.security.SecurityException e) {
- log.warn("PVP2x message signature validation FAILED.", e);
- throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
- }
- }
-
- private void verifyRequest(RequestAbstractType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException {
- SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
- try {
- profileValidator.validate(samlObj.getSignature());
- performSchemaValidation(samlObj.getDOM());
-
- } catch (ValidationException e) {
- log.warn("Signature is not conform to SAML signature profile", e);
- throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
-
- } catch (SchemaValidationException e) {
- throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
-
- }
-
- CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add( new EntityIDCriteria(samlObj.getIssuer().getValue()) );
- criteriaSet.add( new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) );
- criteriaSet.add( new UsageCriteria(UsageType.SIGNING) );
-
- try {
- if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) {
- throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
- }
- } catch (org.opensaml.xml.security.SecurityException e) {
- log.warn("PVP2x message signature validation FAILED.", e);
- throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
- }
- }
-
- protected void performSchemaValidation(Element source) throws SchemaValidationException {
-
- String err = null;
- try {
- Schema test = SAMLSchemaBuilder.getSAML11Schema();
- Validator val = test.newValidator();
- val.validate(new DOMSource(source));
- log.debug("Schema validation check done OK");
- return;
-
- } catch (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 (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("pvp2.22", new Object[]{err});
-
- }
-
-}
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
new file mode 100644
index 00000000..e0a3ab8e
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.impl.verification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
+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;
+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
+ * signature
+ * @throws Exception In case of a general
+ * error
+ */
+ public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine)
+ throws SecurityException, Exception {
+ try {
+ if (msg instanceof PvpSProfileRequest
+ && ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) {
+ verifyRequest((RequestAbstractType) ((PvpSProfileRequest) msg).getSamlRequest(),
+ sigTrustEngine);
+ } else if (msg instanceof PvpSProfileResponse) {
+ verifyIdpResponse(((PvpSProfileResponse) msg).getResponse(), sigTrustEngine);
+
+ } else {
+ log.warn("SAML2 message type: {} not supported", msg.getClass().getName());
+ throw new EaafProtocolException("internal.pvp.99", null);
+
+ }
+
+ } catch (final InvalidProtocolRequestException e) {
+ if (StringUtils.isEmpty(msg.getEntityID())) {
+ throw e;
+
+ }
+ 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.");
+
+ if (msg instanceof PvpSProfileRequest
+ && ((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());
+ performSchemaValidation(samlObj.getDOM());
+
+ } catch (final SignatureException e) {
+ log.warn("Signature is not conform to SAML signature profile", e);
+ throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage() }, e);
+
+ } catch (final SchemaValidationException e) {
+ throw new InvalidProtocolRequestException(ERROR_03, new Object[] { e.getMessage() }, e);
+
+ }
+
+ final CriteriaSet criteriaSet = new CriteriaSet();
+ criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue()));
+ criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS));
+ criteriaSet.add(new EntityRoleCriterion(defaultElementName));
+ criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
+
+ try {
+ if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) {
+ throw new InvalidProtocolRequestException(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(ERROR_10, new Object[] {e.getMessage()}, e);
+
+ }
+ }
+
+ private void verifyRequest(final RequestAbstractType samlObj,
+ final SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException {
+ final SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
+ try {
+ profileValidator.validate(samlObj.getSignature());
+ performSchemaValidation(samlObj.getDOM());
+
+ } catch (final SignatureException e) {
+ log.warn("Signature is not conform to SAML signature profile", e);
+ throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e);
+
+ } catch (final SchemaValidationException e) {
+ throw new InvalidProtocolRequestException(ERROR_03, new Object[] { e.getMessage() }, e);
+
+ }
+
+ final CriteriaSet criteriaSet = new CriteriaSet();
+ criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue()));
+ criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS));
+ criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
+ criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
+
+ try {
+ if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) {
+ throw new InvalidProtocolRequestException(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(ERROR_10, new Object[] {e.getMessage()}, e);
+
+ }
+
+ }
+
+ 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" });
+
+ }
+ 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" });
+
+ }
+
+ } 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" });
+
+ }
+ }
+
+ 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/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
index 9c60d724..8bc7508c 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -1 +1 @@
-at.gv.egiz.eaaf.modules.pvp2.PVP2SProfileCoreSpringResourceProvider \ No newline at end of file
+at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
index 2cbcce20..72cf9677 100644
--- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml
@@ -1,30 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!--
- -->
-
-<!--
- -->
<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
-
- <bean id="PVPMetadataBuilder"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPMetadataBuilder" />
-
- <bean id="PVPPOSTBinding"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" />
-
- <bean id="PVPRedirectBinding"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" />
-
- <bean id="PVPSOAPBinding"
- class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" />
-
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="pvpLogMessageSource"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.logging.PvpModuleMessageSource" />
+
+ <bean id="pvpMetadataResolverFactory"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory"/>
+
+ <bean id="PVPMetadataBuilder"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder" />
+
+ <bean id="PvpPostBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" />
+
+ <bean id="PvpRedirectBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" />
+
+ <bean id="PvpSoapBinding"
+ class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" />
+
+ <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_core/src/main/resources/messages/pvp_messages.properties b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
new file mode 100644
index 00000000..824f17d4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties
@@ -0,0 +1,31 @@
+internal.pvp.00=KeyStore: {0} Key with alias: {0} not found or contains no PrivateKey.
+internal.pvp.01=KeyStore: {0} contains an unsupported key with alias: {1}
+internal.pvp.02=PVP message contains no signature.
+internal.pvp.03=Schema-validation of SAML2 message failed with error: {0}
+internal.pvp.04=Can not initialize metadata provider for metadata: {0}
+internal.pvp.05=Can not initialize metadata provider for metadata: {0}. Reason: {1}
+internal.pvp.06=SSL-Server certificate for metadata: {0} not trusted. Details: {1}
+internal.pvp.07=Signature verification for metadata: {0} FAILED. Details: {1}
+internal.pvp.08=Schema validation for metadata: {0} FAILED. Details: {1}
+internal.pvp.09=Can not initialize metadata provider for metadata: {0}. Details: {1}
+internal.pvp.10=Signature verification of SAML2 message FAILED. Reason: {0}
+internal.pvp.11=General SAML2 message validation error. Reason: {0}
+internal.pvp.12=SAML2 metadata: {0} is NOT signed
+internal.pvp.13=SAML2 metadata generation failed. Reason: {0}
+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}
+pvp2.24=General error during SAML2 Auth. request pre-processing. Reason: {0}
+
+internal.pvp.95=OpenSAML {0}-binding message {1} failed. Reason: {2}
+internal.pvp.96=OpenSAML signing FAILED with key: {0}. Reason: {1}
+internal.pvp.97=Key with EntityIdentifier: {0} has an unsupported type: {1}
+internal.pvp.98=PVP module has an internal error. Reason: {0}
+internal.pvp.99=PVP module has an generic internal error.
+
+
+
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java
new file mode 100644
index 00000000..d5186857
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java
@@ -0,0 +1,328 @@
+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.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.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.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.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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.Assert;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+
+public abstract class AbstractSamlVerificationEngine {
+
+ @Autowired
+ private PvpMetadataResolverFactory metadataResolverFactory;
+ @Autowired
+ private SamlVerificationEngine verifyEngine;
+ @Autowired
+ protected 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();
+
+ }
+ protected abstract String getMetadataJunitJKeystore();
+
+ protected abstract String getMetadataClassPathEntityPath();
+
+ protected abstract String getAuthnRequestWithoutSigPath();
+
+ protected abstract String getResponseWithSigPath();
+
+ protected abstract String getResponseWithoutSigPath();
+
+
+ @Test
+ public void validateSamlRequestSuccess() throws SecurityException, Exception {
+
+ final String authnReqPath = getAuthnRequestWithoutSigPath();
+ final String metadataPath = getMetadataClassPathEntityPath();
+ 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 = getAuthnRequestWithoutSigPath();
+ final String metadataPath = getMetadataJunitJKeystore();
+ 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 verifyResponseSuccessTest() throws Pvp2InternalErrorException, SecurityException, Exception {
+ metadataProvider.runGarbageCollector();
+
+ final String authnReqPath = getResponseWithoutSigPath();
+ final String metadataPath = getMetadataClassPathEntityPath();
+ 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 = getResponseWithoutSigPath();
+ final String metadataPath = getMetadataClassPathEntityPath();
+ 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 = getResponseWithoutSigPath();
+ final String metadataPath = getMetadataClassPathEntityPath();
+ 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 = getResponseWithSigPath();
+ final String metadataPath = getMetadataClassPathEntityPath();
+ 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 = getResponseWithoutSigPath();
+ final String metadataPath = getMetadataJunitJKeystore();
+ 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());
+
+ }
+ }
+
+ protected 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(),
+ AbstractSamlVerificationEngine.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);
+ }
+
+ protected 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(),
+ AbstractSamlVerificationEngine.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);
+
+ }
+
+ protected 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/CredentialProviderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java
new file mode 100644
index 00000000..c784e392
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java
@@ -0,0 +1,613 @@
+package at.gv.egiz.eaaf.modules.pvp2.test;
+
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.xml.security.algorithms.JCEMapper;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({
+ "/spring/test_eaaf_core_map_config.beans.xml",
+ "/spring/SpringTest-context_lazy.xml",
+ "/spring/eaaf_utils.beans.xml"
+ })
+public class CredentialProviderTest {
+
+ private static final String HSM_FACASE_HOST = "eid.a-sit.at";
+ private static final String HSM_FACASE_PORT = "9050";
+ private static final String HSM_FACASE_SSL_TRUST = "src/test/resources/data/hsm_facade_trust_root.crt";
+ private static final String HSM_FACASE_USERNAME = "authhandler-junit";
+ private static final String HSM_FACASE_PASSWORD = "supersecret123";
+ private static final String PATH_JKS_WITH_TRUST_CERTS = "src/test/resources/data/junit.jks";
+ private static final String PATH_JKS_WITHOUT_TRUST_CERTS = "src/test/resources/data/junit_without_trustcerts.jks";
+
+ private static final String HSM_FACASE_KEYSTORE_NAME = "authhandler";
+
+ private static final String ALIAS_METADATA = "meta";
+ private static final String ALIAS_SIGN = "sig";
+ private static final String ALIAS_ENC = "meta";
+
+ private static final String PASSWORD = "password";
+
+ private static final String HSM_FACADE_KEY_ALIAS = "authhandler-sign";
+
+
+ @Autowired private ApplicationContext context;
+ @Autowired private DummyAuthConfigMap config;
+
+ /**
+ * jUnit test initializer.
+ */
+ @Before
+ public void initialize() {
+ config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, HSM_FACASE_HOST);
+ config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, HSM_FACASE_PORT);
+ config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, HSM_FACASE_SSL_TRUST);
+ config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, HSM_FACASE_USERNAME);
+ config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, HSM_FACASE_PASSWORD);
+
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_NAME, HSM_FACASE_KEYSTORE_NAME);
+
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITH_TRUST_CERTS);
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PASSWORD, PASSWORD);
+
+ config.removeConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS);
+ config.removeConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD);
+
+ config.removeConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS);
+ config.removeConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD);
+
+ config.removeConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS);
+ config.removeConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD);
+
+ JCEMapper.setProviderId(null);
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void noKeyStoreUrl() {
+ config.removeConfigValue(DummyCredentialProvider.KEYSTORE_PATH);
+ try {
+ context.getBean(DummyCredentialProvider.class);
+ Assert.fail("No KeyStore not detected");
+
+ } catch (final BeansException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,
+ e.getCause(), "Wrong exception");
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void noKeyStore() {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, "src/test/resources/config/notExist.p12");
+ try {
+ context.getBean(DummyCredentialProvider.class);
+ Assert.fail("No KeyStore not detected");
+
+ } catch (final BeansException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,
+ e.getCause(), "Wrong exception");
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void noWrongKeyStorePassword() {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PASSWORD, "test");
+ try {
+ context.getBean(DummyCredentialProvider.class);
+ Assert.fail("No KeyStore not detected");
+
+ } catch (final BeansException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafFactoryException.class,
+ e.getCause(), "Wrong exception");
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfigurationWrongAlias() {
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMetaDataSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMessageSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMessageEncryptionCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfigurationWrongPassword() {
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMetaDataSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMessageSigningCredential();
+ Assert.fail("No message signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ final EaafX509Credential encCred = credential.getMessageEncryptionCredential();
+ Assert.assertNull("No encryption credentials not detected", encCred);
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfigurationValidAliasWrongPassword() {
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ ALIAS_METADATA);
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMetaDataSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS,
+ ALIAS_SIGN);
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMessageSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS,
+ ALIAS_ENC);
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ credential.getMessageEncryptionCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfigurationWrongAliasValidPassword() {
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD,
+ PASSWORD);
+ credential.getMetaDataSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD,
+ PASSWORD);
+ credential.getMessageSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD,
+ PASSWORD);
+ credential.getMessageEncryptionCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void validonfiguration() throws CredentialsNotAvailableException {
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ ALIAS_METADATA);
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD,
+ PASSWORD);
+
+ checkCredential(credential.getMetaDataSigningCredential(),
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA);
+
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS,
+ ALIAS_SIGN);
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD,
+ PASSWORD);
+ checkCredential(credential.getMessageSigningCredential(),
+ PvpConstants.DEFAULT_SIGNING_METHODE_EC,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC);
+
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS,
+ ALIAS_ENC);
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD,
+ PASSWORD);
+ checkCredential(credential.getMessageEncryptionCredential(),
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA);
+
+
+ final List<X509Certificate> trustCerts = credential.getTrustedCertificates();
+ Assert.assertNotNull("TrustCerts are null", trustCerts);
+ Assert.assertFalse("TrustCerts not empty", trustCerts.isEmpty());
+ Assert.assertEquals("# of Trustcerts", 2, trustCerts.size());
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void validonfigurationWithOutTrustCerts() throws CredentialsNotAvailableException {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITHOUT_TRUST_CERTS);
+
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ "RSA-SIG_" + RandomStringUtils.randomAlphabetic(10));
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG,
+ "EC-SIG_" + RandomStringUtils.randomAlphabetic(10));
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG,
+ "RSA_ENC_" + RandomStringUtils.randomAlphabetic(10));
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG,
+ "EC-ENC_" + RandomStringUtils.randomAlphabetic(10));
+
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ ALIAS_METADATA);
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD,
+ PASSWORD);
+
+ checkCredential(credential.getMetaDataSigningCredential(),
+ config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG),
+ config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG));
+
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS,
+ ALIAS_SIGN);
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD,
+ PASSWORD);
+ checkCredential(credential.getMessageSigningCredential(),
+ config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG),
+ config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG));
+
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS,
+ ALIAS_ENC);
+ config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD,
+ PASSWORD);
+ checkCredential(credential.getMessageEncryptionCredential(),
+ config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG),
+ config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG));
+
+ final List<X509Certificate> trustCerts = credential.getTrustedCertificates();
+ Assert.assertNotNull("TrustCerts are null", trustCerts);
+ Assert.assertTrue("TrustCerts not empty", trustCerts.isEmpty());
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void otherKeyStoreTypeAlreadyLoaded() throws CredentialsNotAvailableException {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITHOUT_TRUST_CERTS);
+
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG,
+ "RSA-SIG_" + RandomStringUtils.randomAlphabetic(10));
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG,
+ "EC-SIG_" + RandomStringUtils.randomAlphabetic(10));
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG,
+ "RSA_ENC_" + RandomStringUtils.randomAlphabetic(10));
+ config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG,
+ "EC-ENC_" + RandomStringUtils.randomAlphabetic(10));
+
+ try {
+ JCEMapper.setProviderId(RandomStringUtils.randomAlphabetic(5));
+
+ context.getBean(DummyCredentialProvider.class);
+
+ } catch (final BeansException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,
+ e.getCause(), "Wrong exception");
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfiguration() {
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ credential.getMetaDataSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ credential.getMessageSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ final EaafX509Credential encCred = credential.getMessageEncryptionCredential();
+ Assert.assertNull("No encryption signing credentials not detected", encCred);
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfigurationPkcs12() {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH,
+ "src/test/resources/data/junit_without_trustcerts.p12");
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ credential.getMetaDataSigningCredential();
+ Assert.fail("No Metadata signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ credential.getMessageSigningCredential();
+ Assert.fail("No message signing credentials not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+
+ try {
+ final EaafX509Credential encCred = credential.getMessageEncryptionCredential();
+ Assert.assertNull("No encryption signing credentials not detected", encCred);
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01"));
+
+ }
+ }
+
+ @Test
+ @DirtiesContext
+ public void hasFacadeMissingKeyStoreName() {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_TYPE,
+ KeyStoreConfiguration.KeyStoreType.HSMFACADE.getKeyStoreType());
+ config.removeConfigValue(DummyCredentialProvider.KEYSTORE_NAME);
+
+ try {
+ context.getBean(DummyCredentialProvider.class);
+ Assert.fail("No KeyStore not detected");
+
+ } catch (final BeansException e) {
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,
+ e.getCause(), "Wrong exception");
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void hasFacadeWrongAlias() {
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_TYPE,
+ KeyStoreConfiguration.KeyStoreType.HSMFACADE.getKeyStoreType());
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_NAME, HSM_FACASE_KEYSTORE_NAME);
+
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+
+ try {
+ checkCredential(credential.getMetaDataSigningCredential(),
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA);
+ Assert.fail("Wrong 'alias' not detected");
+
+ } catch (final CredentialsNotAvailableException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.01", e.getErrorId());
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void validConfigurationHsmFacade() throws CredentialsNotAvailableException {
+
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_TYPE,
+ KeyStoreConfiguration.KeyStoreType.HSMFACADE.getKeyStoreType());
+ config.putConfigValue(DummyCredentialProvider.KEYSTORE_NAME, HSM_FACASE_KEYSTORE_NAME);
+
+ final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS,
+ HSM_FACADE_KEY_ALIAS);
+ config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD,
+ PASSWORD);
+
+
+ checkCredential(credential.getMetaDataSigningCredential(),
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA);
+
+ config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS,
+ HSM_FACADE_KEY_ALIAS);
+
+ checkCredential(credential.getMessageSigningCredential(),
+ PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA);
+
+
+ final List<X509Certificate> trustCerts = credential.getTrustedCertificates();
+ Assert.assertNotNull("TrustCerts are null", trustCerts);
+ Assert.assertTrue("TrustCerts not empty", trustCerts.isEmpty());
+
+ }
+
+
+ private void checkCredential(EaafX509Credential metaDataSigningCredential, String sigAlg, String keyEncAlg) {
+ Assert.assertNotNull("No metadata signing credentials", metaDataSigningCredential);
+ Assert.assertNotNull("SigAlg is null",
+ metaDataSigningCredential.getSignatureAlgorithmForSigning());
+ Assert.assertNotNull("KeyEncAlg is null",
+ metaDataSigningCredential.getKeyEncryptionAlgorithmForDataEncryption());
+ Assert.assertFalse("SigAlg is empty",
+ metaDataSigningCredential.getSignatureAlgorithmForSigning().isEmpty());
+ Assert.assertFalse("KeyEncAlg is empty",
+ metaDataSigningCredential.getKeyEncryptionAlgorithmForDataEncryption().isEmpty());
+
+ Assert.assertEquals("Wrong SigAlg", sigAlg,
+ metaDataSigningCredential.getSignatureAlgorithmForSigning());
+ Assert.assertEquals("Wrong KeyEncAlg", keyEncAlg,
+ metaDataSigningCredential.getKeyEncryptionAlgorithmForDataEncryption());
+
+ }
+}
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/PvpCoreMessageSourceTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/PvpCoreMessageSourceTest.java
new file mode 100644
index 00000000..b94ed8cc
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/PvpCoreMessageSourceTest.java
@@ -0,0 +1,43 @@
+package at.gv.egiz.eaaf.modules.pvp2.test;
+
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml",
+"/spring/test_eaaf_core_spring_config.beans.xml",
+"/spring/eaaf_utils.beans.xml" })
+@TestPropertySource(locations = { "/config/config_1.props" })
+public class PvpCoreMessageSourceTest {
+
+ @Autowired
+ private ResourceLoader loader;
+ @Autowired(required = false)
+ private List<IMessageSourceLocation> messageSources;
+
+ @Test
+ public void checkMessageSources() {
+ Assert.assertNotNull("No messageSource", messageSources);
+
+ for (final IMessageSourceLocation messageSource : messageSources) {
+ Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation());
+
+ for (final String el : messageSource.getMessageSourceLocation()) {
+ final Resource messages = loader.getResource(el + ".properties");
+ Assert.assertTrue("Source not exist", messages.exists());
+
+ }
+ }
+ }
+}
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..64bfb8f6
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java
@@ -0,0 +1,474 @@
+package at.gv.egiz.eaaf.modules.pvp2.test;
+
+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.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.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.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.Test;
+import org.junit.runner.RunWith;
+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.Response;
+import org.opensaml.saml.saml2.core.StatusCode;
+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",
+ "/spring/eaaf_utils.beans.xml" })
+@TestPropertySource(locations = { "/config/config_1.props" })
+public class SamlVerificationEngineTest extends AbstractSamlVerificationEngine {
+
+ @Autowired
+ private SamlVerificationEngine verifyEngine;
+ @Autowired
+ private DummyCredentialProvider credentialProvider;
+
+ @Autowired DummyMetadataProvider metadataProvider;
+ @Autowired IConfiguration authConfig;
+
+ @Override
+ protected String getMetadataClassPathEntityPath() {
+ return "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml";
+
+ }
+
+ @Override
+ protected String getMetadataJunitJKeystore() {
+ return "classpath:/data/pvp_metadata_junit_keystore.xml";
+ }
+
+ @Override
+ protected String getAuthnRequestWithoutSigPath() {
+ return "/data/AuthRequest_without_sig_1.xml";
+
+ }
+
+ @Override
+ protected String getResponseWithSigPath() {
+ return "/data/Response_with_sig_1.xml";
+ }
+
+ @Override
+ protected String getResponseWithoutSigPath() {
+ return "/data/Response_without_sig_1.xml";
+ }
+
+ @Test
+ public void validateSamlRequestWrongSignatureAlg() throws SecurityException, Exception {
+
+ final String authnReqPath = getAuthnRequestWithoutSigPath();
+ final String metadataPath = getMetadataJunitJKeystore();
+ 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 validateSamlInvalidRequest() throws SecurityException, Exception {
+
+ final String authnReqPath = "/data/AuthRequest_without_sig_missing_id.xml";
+ final String metadataPath = getMetadataJunitJKeystore();
+ 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 verifyAssertionSucessNotEncrypted() throws SamlSigningException, Pvp2MetadataException,
+ CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption {
+ final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml";
+ final String metadataPath = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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 = getMetadataJunitJKeystore();
+ 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());
+
+ }
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java
new file mode 100644
index 00000000..5b06a73f
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java
@@ -0,0 +1,70 @@
+package at.gv.egiz.eaaf.modules.pvp2.test;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml",
+ "/spring/test_eaaf_core_spring_config.beans.xml",
+ "/spring/eaaf_utils.beans.xml" })
+@TestPropertySource(locations = { "/config/config_3.props" })
+public class SamlVerificationEngineWithHsmFacadeTest extends AbstractSamlVerificationEngine {
+
+ @Override
+ protected String getMetadataClassPathEntityPath() {
+ return "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml";
+
+ }
+
+ @Override
+ protected String getMetadataJunitJKeystore() {
+ return "classpath:/data/pvp_metadata_junit_keystore.xml";
+ }
+
+ @Override
+ protected String getAuthnRequestWithoutSigPath() {
+ return "/data/AuthRequest_without_sig_1.xml";
+
+ }
+
+ @Override
+ protected String getResponseWithSigPath() {
+ return "/data/Response_with_sig_1.xml";
+ }
+
+ @Override
+ protected String getResponseWithoutSigPath() {
+ return "/data/Response_without_sig_1.xml";
+ }
+
+ @Test
+ public void validateSamlRequestWrongSignatureAlg() throws SecurityException, Exception {
+
+ final String authnReqPath = getAuthnRequestWithoutSigPath();
+ final String metadataPath = getMetadataJunitJKeystore();
+ final String spEntityId = metadataPath;
+
+ metadataProvider.runGarbageCollector();
+
+ final EaafX509Credential cred = credentialProvider.getMetaDataSigningCredential();
+ cred.setSignatureAlgorithmForSigning(SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5);
+ try {
+ initializeAuthnRequest(spEntityId, metadataPath, authnReqPath,
+ cred);
+ org.junit.Assert.fail("Wrong SigAlg not detected");
+
+ } catch (final SamlSigningException e) {
+ org.junit.Assert.assertEquals("Wrong errorCode", "internal.pvp.96", e.getErrorId());
+
+ }
+ }
+
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java
new file mode 100644
index 00000000..147199a5
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java
@@ -0,0 +1,764 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.binding;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+import java.util.Map;
+
+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.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 org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.joda.time.DateTime;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.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;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import net.shibboleth.utilities.java.support.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;
+import okhttp3.mockwebserver.MockWebServer;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml",
+ "/spring/test_eaaf_core_spring_config.beans.xml",
+ "/spring/eaaf_utils.beans.xml"})
+@TestPropertySource(locations = {"/config/config_1.props"})
+public class PostBindingTest {
+
+ public static final String HTTP_FORM_RELAYSTATE = "RelayState=";
+ public static final String HTTP_FORM_SAMLREQ = "SAMLRequest=";
+ public static final String HTTP_FORM_SAMLRESP = "SAMLResponse=";
+
+ @Autowired private PostBinding bindingImpl;
+ @Autowired private DummyCredentialProvider credentialProvider;
+ @Autowired private DummyGuiBuilderConfigurationFactory guiBuilderFactory;
+ @Autowired private PvpMetadataResolverFactory metadataResolverFactory;
+ @Autowired private IHttpClientFactory httpClientFactory;
+
+ private static MockWebServer mockWebServer;
+ private static HttpUrl mockServerUrl;
+
+ protected MockHttpServletRequest httpReq;
+ protected MockHttpServletResponse httpResp;
+ protected IRequest pendingReq;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ mockWebServer = new MockWebServer();
+ mockServerUrl = mockWebServer.url("/sp/metadata");
+ }
+
+ /**
+ * Test initializer.
+ *
+ */
+ @Before
+ public void initialize() {
+ httpReq = new MockHttpServletRequest();
+ httpResp = new MockHttpServletResponse();
+
+ pendingReq = new TestRequestImpl();
+
+ }
+
+ @Test
+ public void checkCanHandle() {
+ httpReq.setMethod("POST");
+ Assert.assertTrue("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+
+ httpReq.setMethod("GET");
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+ }
+
+ @Test
+ public void 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";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+ Assert.fail("Wrong http end-point not detected");
+
+ } catch (final Pvp2Exception e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId());
+ Assert.assertNotNull("Parameters null", e.getParams());
+ Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length);
+
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestMissingSignature() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2MetadataException {
+ final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+ Assert.fail("Missing signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId());
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestWrongSignature() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2Exception {
+ final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")));
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+ Assert.fail("Invalid signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type");
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId());
+ Assert.assertNotNull("No error params", e.getParams());
+ Assert.assertEquals("Wrong param size", 1, e.getParams().length);
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestMsgExpired() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "https://eidas-test.bmi.gv.at/ms_connector/pvp/post";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_moaid_test.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = new String(IOUtils.toByteArray(
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_withsig_expired.b64")), "UTF-8");
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+ Assert.fail("Expired msg not detected");
+
+ } catch (final Pvp2Exception e) {
+ org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, "Wrong Exception type");
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId());
+ Assert.assertNotNull("No error params", e.getParams());
+ Assert.assertEquals("Wrong param size", 1, e.getParams().length);
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestSuccessMetadataReloadRequired() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+
+ final String b64AuthnReq = generateSaml2AuthnRequest(
+ credentialProvider.getMetaDataSigningCredential());
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_wrong_sig.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_junit_keystore.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ null, "jUnit test", httpClientFactory.getHttpClient());
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState not null", msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertTrue("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void decodeRequestSuccessWithRelayStateRsaSig() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphanumeric(10);
+
+ final String b64AuthnReq = generateSaml2AuthnRequest(
+ credentialProvider.getMetaDataSigningCredential());
+ 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());
+
+ }
+
+ @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());
+ final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class);
+ issuer.setValue("https://demo.egiz.gv.at/demoportal_demologin/");
+ authnReq.setIssuer(issuer);
+
+ final RequestAbstractType signedAuthn = Saml2Utils.signSamlObject(authnReq, credentialProvider.getMessageSigningCredential(), true);
+ final 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");
+
+ final 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());
+
+ final XMLObject reqAttrs = parsedAuthnReq.getExtensions().getUnknownXMLObjects().get(0);
+ org.springframework.util.Assert.isInstanceOf(EaafRequestedAttributes.class, reqAttrs, "Wrong requested Attributes type");
+ final 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());
+
+ final 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";
+
+ final String b64AuthnReq = generateSaml2AuthnRequest(
+ credentialProvider.getMessageSigningCredential());
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.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 (final RuntimeException e) { }
+
+ }
+
+ @Test
+ public void decodeResponseSuccess() throws MessageDecodingException, SecurityException,
+ IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final String b64AuthnReq = generateSaml2Response(credentialProvider.getMetaDataSigningCredential());
+ httpReq.setMethod("POST");
+ httpReq.addParameter("SAMLRequest", b64AuthnReq);
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertTrue("Wrong isVerified flag", msg.isVerified());
+
+ org.springframework.util.Assert.isInstanceOf(PvpSProfileResponse.class, msg, "Inbound message is of wrong type");
+
+ }
+
+ @Test
+ public void encodeRequestSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMessageSigningCredential(), pendingReq);
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertTrue("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+ final String httpRelayState = extractParamFromHttpForm(http, HTTP_FORM_RELAYSTATE);
+ Assert.assertEquals("Wrong RelayState", relayState, httpRelayState);
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertTrue("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+ final String httpRelayState = extractParamFromHttpForm(http, HTTP_FORM_RELAYSTATE);
+ Assert.assertEquals("Wrong RelayState", relayState, httpRelayState);
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ @Test
+ public void encodeResponseSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception {
+
+ //build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+
+ //validate
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/html", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE));
+
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP));
+ final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP);
+ checkSamlMessageSigned(httpSamlReq);
+
+ }
+
+ private IVelocityGuiBuilderConfiguration createDummyGuiConfig() {
+ return new IVelocityGuiBuilderConfiguration() {
+
+ @Override
+ public Map<String, Object> getViewParameters() {
+ return null;
+ }
+
+ @Override
+ public String getViewName() {
+ return "SAML2 Post-Binding";
+ }
+
+ @Override
+ public String getDefaultContentType() {
+ return null;
+ }
+
+ @Override
+ public InputStream getTemplate(String viewName) {
+ return PostBindingTest.class.getResourceAsStream("/data/pvp_postbinding_template.html");
+ }
+
+ @Override
+ public String getClasspathTemplateDir() {
+ return null;
+
+ }
+ };
+ }
+
+ private void checkSamlMessageSigned(String b64Msg) throws ParserConfigurationException,
+ SAXException, IOException, UnmarshallingException {
+ final Element httpSamlReqElment = DomUtils.parseXmlNonValidating(
+ new ByteArrayInputStream(Base64.getDecoder().decode(b64Msg)));
+
+ final UnmarshallerFactory unmarshallerFactory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
+ final Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(httpSamlReqElment);
+ final SignableSAMLObject msg = (SignableSAMLObject) unmarshaller.unmarshall(httpSamlReqElment);
+ Assert.assertTrue("SAML msg not signed", msg.isSigned());
+
+ }
+
+ private String extractParamFromHttpForm(String http, String httpFormRelaystate) {
+ final int startIndex = http.indexOf(httpFormRelaystate) + httpFormRelaystate.length();
+ final int endIndex = http.indexOf("\"", startIndex);
+ return http.substring(startIndex, endIndex);
+
+ }
+
+ private String generateSaml2AuthnRequest(EaafX509Credential credentials)
+ throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException,
+ UnsupportedEncodingException {
+ final MockHttpServletRequest intHttpReq = new MockHttpServletRequest();
+ final MockHttpServletResponse intHttpResp = new MockHttpServletResponse();
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+ authnReq.setIssueInstant(DateTime.now());
+
+ bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null,
+ credentials, pendingReq);
+
+ Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus());
+ final String http = intHttpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ));
+ return extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ);
+
+ }
+
+ private String generateSaml2Response(EaafX509Credential credentials)
+ throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException,
+ UnsupportedEncodingException {
+ final MockHttpServletRequest intHttpReq = new MockHttpServletRequest();
+ final MockHttpServletResponse intHttpResp = new MockHttpServletResponse();
+ guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+ final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+ response.setIssueInstant(DateTime.now());
+
+ bindingImpl.encodeResponse(intHttpReq, intHttpResp, response, "http://testservice.org", null,
+ credentials, pendingReq);
+
+ Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus());
+ final String http = intHttpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP));
+ return extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP);
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
new file mode 100644
index 00000000..37e4acd1
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java
@@ -0,0 +1,854 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.binding;
+
+import java.io.IOException;
+import java.net.URLDecoder;
+
+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.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.messaging.decoder.MessageDecodingException;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.xml.sax.SAXException;
+
+import net.shibboleth.utilities.java.support.net.URIComparator;
+import net.shibboleth.utilities.java.support.net.URISupport;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+import okhttp3.HttpUrl;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml",
+ "/spring/test_eaaf_core_spring_config.beans.xml",
+ "/spring/eaaf_utils.beans.xml" })
+@TestPropertySource(locations = { "/config/config_1.props" })
+public class RedirectBindingTest {
+
+ public static final String HTTP_FORM_RELAYSTATE = "RelayState";
+ public static final String HTTP_FORM_RELAYSTATE_PARAM = HTTP_FORM_RELAYSTATE + "=";
+
+ public static final String HTTP_FORM_SAMLREQ = "SAMLRequest";
+ public static final String HTTP_FORM_SAMLREQ_PARAM = HTTP_FORM_SAMLREQ + "=";
+ public static final String HTTP_FORM_SAMLRESP = "SAMLResponse";
+ public static final String HTTP_FORM_SAMLRESP_PARM = HTTP_FORM_SAMLRESP + "=";
+
+ public static final String HTTP_REDIRECT_SIGALG = "SigAlg";
+ public static final String HTTP_REDIRECT_SIGALG_PARAM = HTTP_REDIRECT_SIGALG + "=";
+ public static final String HTTP_REDIRECT_SIGNATURE = "Signature";
+ public static final String HTTP_REDIRECT_SIGNATURE_PARAM = HTTP_REDIRECT_SIGNATURE + "=";
+
+ @Autowired
+ private RedirectBinding bindingImpl;
+ @Autowired
+ private DummyCredentialProvider credentialProvider;
+ @Autowired
+ private PvpMetadataResolverFactory metadataResolverFactory;
+ @Autowired private IHttpClientFactory httpClientFactory;
+
+ private static MockWebServer mockWebServer;
+ private static HttpUrl mockServerUrl;
+
+ protected MockHttpServletRequest httpReq;
+ protected MockHttpServletResponse httpResp;
+ protected IRequest pendingReq;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ mockWebServer = new MockWebServer();
+ mockServerUrl = mockWebServer.url("/sp/metadata");
+ }
+
+ /**
+ * Test initializer.
+ *
+ */
+ @Before
+ public void initialize() {
+ httpReq = new MockHttpServletRequest();
+ httpResp = new MockHttpServletResponse();
+
+ pendingReq = new TestRequestImpl();
+
+ }
+
+ @Test
+ public void checkCanHandle() {
+ httpReq.setMethod("POST");
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+
+ httpReq.setMethod("GET");
+ Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq));
+ Assert.assertTrue("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq));
+ }
+
+ @Test
+ public void 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";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%"
+ + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli"
+ + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps"
+ + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv"
+ + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402"
+ + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI"
+ + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2"
+ + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2"
+ + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86"
+ + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg"
+ + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc"
+ + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D");
+
+ httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+ Assert.fail("Missing signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ public void decodeRequestWrongEndpoint() throws MessageDecodingException,
+ SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://wrongEndPoint.org";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%"
+ + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli"
+ + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps"
+ + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv"
+ + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402"
+ + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI"
+ + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2"
+ + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2"
+ + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86"
+ + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg"
+ + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc"
+ + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D");
+
+ httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()),
+ "UTF-8"));
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+ Assert.fail("Wrong signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId());
+ Assert.assertNotNull("Parameters null", e.getParams());
+ Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length);
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestWrongSignature() throws MessageDecodingException,
+ SecurityException, IOException, Pvp2Exception {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%"
+ + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli"
+ + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps"
+ + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv"
+ + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402"
+ + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI"
+ + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2"
+ + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2"
+ + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86"
+ + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg"
+ + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc"
+ + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D");
+
+ httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()),
+ "UTF-8"));
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+ Assert.fail("Wrong signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type");
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId());
+ Assert.assertNotNull("No error params", e.getParams());
+ Assert.assertEquals("Wrong param size", 1, e.getParams().length);
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestExpired() throws MessageDecodingException,
+ SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException,
+ XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkj2RFJsQujAQFAnTD1nQ97FIoNu1qkyVPop20v36KYwcusPVgQ"
+ + "AeLeiQfH0mvbo6V9FowVmgVk5AGxAOV6VyoMiY%2FHm5nS3KTrCyvZFSztMFndQ9%2FGrDoOUdl2fklJo1RTHMrLFO8AsswY7v"
+ + "0yx2LaMBqo1FnWhIvtRYMulRrrWxTgdmBaUUGW5XD0aV3CEQj9g3CGeFovIU4fhuXXSiOHeNnxJr5PjqbPQOpNiXxtpuYPHGAf"
+ + "cFhnsH1MixgnucZL6JwzhdREYT53MGsbVxoi1xhTKIgCmZBNAsWD8Fn5s6na7qMwp%2FEexwUcvWQXg%2FWOZuxEO%2FrwIfqi"
+ + "XerTcXxffjJIvJZ0UEZKBT4QpJTwdZVnEOlKZTilZYt5djda22Qy6fTp9SlUP7KHzMdeO%2Ba%2FS%2FIcArx5OOHq6s%2BzFe"
+ + "H226mEep9XbTB0pO6zNoZ8U1Lkb14qZT6sDbAEWKCpoEpCtanHlp0QpIpw%2BtfqPUbAHm3D25QEY6T9mGs5jjWWjrF76GY1KF"
+ + "%2BIw6HA7WozW9a6pZC47vd9jOB4hXU9zS9gxakvxjU%2F1f2UXf%2BU3NyeR7%2FGZK%2F&SigAlg=http%3A%2F%2Fwww.w3"
+ + ".org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=JogFpk2oimCnBCgE7eZx%2B6yoJu2ZCgus5vM1opkTk"
+ + "OLM9qgNMUJJJbIeA3j2TR%2BWx3pUApnV7ed9CuTBF94b3ELkFdaZAetfLzY8gnPLCBmcYIYkwg3bK7ZQWEBJpjNoU%2BaBHXV"
+ + "OgptLUt0qRWavm%2BiPOUXRWpb0PtgvApTieRk32gBfZbuPOltWjrRCKaa2ulKBjB34LqYdAaIWaVix2sGvg128p6lC7bQ%2Fz"
+ + "wmz6j8S5Vn8snvlg48MlBldTWKSZrUERx3MwTyaB17A617XmX2QKo8fGCQ6O7FF4umFyWGAlujI%2FwqafTfPlaNX2usHynHS6"
+ + "XkH5HWCDSAe3%2BVR1w%3D%3D ");
+
+ httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()),
+ "UTF-8"));
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+ Assert.fail("Expired message not detected");
+
+ } catch (final Pvp2Exception e) {
+ org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e,
+ "Wrong Exception type");
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId());
+ Assert.assertNotNull("No error params", e.getParams());
+ Assert.assertEquals("Wrong param size", 1, e.getParams().length);
+
+ }
+
+ }
+
+ @Test
+ public void decodeRequestSuccess() throws MessageDecodingException,
+ SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException,
+ XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setQueryString(generateAuthnRequest(credentialProvider.getMetaDataSigningCredential()));
+
+ httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()),
+ "UTF-8"));
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg
+ .getEntityID());
+ Assert.assertTrue("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException,
+ Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setQueryString(generateResponse(credentialProvider.getMetaDataSigningCredential()));
+
+ httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()),
+ "UTF-8"));
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNull("RelayState is not null", msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg
+ .getEntityID());
+ Assert.assertTrue("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void decodeResponseSuccessWithRelayStateAndMetadataReload() throws MessageDecodingException,
+ SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException,
+ XMLParserException, UnmarshallingException {
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphanumeric(10);
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_wrong_sig.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_junit_keystore.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ null, "jUnit test", httpClientFactory.getHttpClient());
+
+
+ httpReq.setMethod("GET");
+ httpReq.setRequestURI("http://testservice.org");
+ httpReq.setParameter(HTTP_FORM_RELAYSTATE, relayState);
+ httpReq.setQueryString(generateResponse(credentialProvider.getMetaDataSigningCredential()));
+
+ httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()),
+ "UTF-8"));
+ httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter(
+ httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()),
+ "UTF-8"));
+
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comparator);
+
+ Assert.assertNotNull("PVP msg is null", msg);
+ Assert.assertNotNull("RelayState is null", msg.getRelayState());
+ Assert.assertEquals("RelayState not match", relayState, msg.getRelayState());
+ Assert.assertNotNull("Response is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg
+ .getEntityID());
+ Assert.assertTrue("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void encodeRequestSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException,
+ Pvp2Exception {
+ // build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+ // validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);
+ Assert.assertNull("RelayState parameter", respRelayState);
+
+ }
+
+ @Test
+ public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException,
+ Pvp2Exception {
+ // build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMessageSigningCredential(), pendingReq);
+
+ // validate
+ // validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_EC,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);
+ Assert.assertNull("RelayState parameter", respRelayState);
+
+ }
+
+ @Test
+ public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException,
+ Pvp2Exception {
+
+ // build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+
+ bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+ // validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);
+ Assert.assertNotNull("RelayState parameter", respRelayState);
+ Assert.assertEquals("RelayState not match", relayState,
+ URLDecoder.decode(respRelayState, "UTF-8"));
+
+ }
+
+ @Test
+ public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException,
+ Pvp2Exception {
+
+ // build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = RandomStringUtils.randomAlphabetic(10);
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+ // validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);
+ Assert.assertNotNull("RelayState parameter", respRelayState);
+ Assert.assertEquals("RelayState not match", relayState,
+ URLDecoder.decode(respRelayState, "UTF-8"));
+
+ }
+
+ @Test
+ public void encodeResponseSuccess() throws MessageDecodingException, SecurityException,
+ MessageEncodingException, XMLParserException, UnmarshallingException,
+ CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException,
+ Pvp2Exception {
+
+ // build test data
+ final String serviceUrl = "http://testservice.org";
+ final String relayState = null;
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+ // validate
+ Assert.assertEquals("http StatusCode", 302, httpResp.getStatus());
+ Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength());
+
+ Assert.assertNull("ContentType", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String locationHeader = httpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ Assert.assertFalse("Location header is empty", locationHeader.isEmpty());
+
+ Assert.assertTrue("Wrong redirect URL",
+ locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM));
+
+ final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, true);
+ Assert.assertNotNull("Saml msg is null", respSamlMsg);
+ Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty());
+
+ final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true);
+ Assert.assertNotNull("SigAlg is null", sigAlg);
+ Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty());
+ Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA,
+ URLDecoder.decode(sigAlg, "UTF-8"));
+
+ final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true);
+ Assert.assertNotNull("Saml signature null", samlSig);
+ Assert.assertFalse("Saml signature is empty", samlSig.isEmpty());
+
+ final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false);
+ Assert.assertNull("RelayState parameter", respRelayState);
+
+ }
+
+ private String checkMessagePart(String locationHeader, String httpFormSamlreq, boolean isRequired) {
+ final int startIndex = locationHeader.indexOf(httpFormSamlreq);
+ int endIndex = locationHeader.indexOf("&", startIndex);
+
+ if (isRequired && startIndex == -1) {
+ Assert.fail("Element: " + httpFormSamlreq + " NOT found");
+
+ } else if (startIndex == -1) {
+ return null;
+
+ }
+
+ if (endIndex == -1) {
+ endIndex = locationHeader.length();
+
+ }
+
+ return locationHeader.substring(startIndex + httpFormSamlreq.length(), endIndex);
+
+ }
+
+ private String generateAuthnRequest(EaafX509Credential credential) throws Pvp2Exception,
+ XMLParserException, UnmarshallingException {
+ final MockHttpServletRequest intHttpReq = new MockHttpServletRequest();
+ final MockHttpServletResponse intHttpResp = new MockHttpServletResponse();
+
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+ authnReq.setIssueInstant(DateTime.now());
+
+ bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null,
+ credential, pendingReq);
+
+ Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus());
+ final String locationHeader = intHttpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ return locationHeader.split("\\?")[1];
+
+ }
+
+ private String generateResponse(EaafX509Credential credential) throws Pvp2Exception,
+ XMLParserException, UnmarshallingException {
+ new MockHttpServletRequest();
+ final MockHttpServletRequest intHttpReq = new MockHttpServletRequest();
+ final MockHttpServletResponse intHttpResp = new MockHttpServletResponse();
+
+ final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+ authnReq.setIssueInstant(DateTime.now());
+
+ bindingImpl.encodeResponse(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null,
+ credential, pendingReq);
+
+ Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus());
+ final String locationHeader = intHttpResp.getHeader("Location");
+ Assert.assertNotNull("Location header is null", locationHeader);
+ return locationHeader.split("\\?")[1];
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java
new file mode 100644
index 00000000..f3a7e01d
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java
@@ -0,0 +1,216 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.binding;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding;
+import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare;
+import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
+
+import org.joda.time.DateTime;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.Marshaller;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.soap.soap11.Envelope;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.net.URIComparator;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml",
+ "/spring/test_eaaf_core_spring_config.beans.xml",
+ "/spring/eaaf_utils.beans.xml"})
+@TestPropertySource(locations = {"/config/config_1.props"})
+public class SoapBindingTest {
+
+ @Autowired private SoapBinding bindingImpl;
+ @Autowired private PvpMetadataResolverFactory metadataResolverFactory;
+ @Autowired private DummyCredentialProvider credentialProvider;
+
+ protected MockHttpServletRequest httpReq;
+ protected MockHttpServletResponse httpResp;
+ protected IRequest pendingReq;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * Test initializer.
+ *
+ */
+ @Before
+ public void initialize() {
+ httpReq = new MockHttpServletRequest();
+ httpResp = new MockHttpServletResponse();
+
+ pendingReq = new TestRequestImpl();
+
+ }
+
+ @Test
+ public void withoutSig() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException {
+ final String serviceUrl = "https://localhost/pvp2/post";
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+ payload.setIssueInstant(DateTime.now());
+ final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload);
+ final Marshaller marshaller = Constraint.isNotNull(
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped),
+ "SOAP Envelope marshaller not available");
+ final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream();
+ SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut);
+ httpReq.setMethod("POST");
+ httpReq.setContentType("text/xml");
+ httpReq.setContent(arrayOut.toByteArray());
+
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider,
+ SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+ Assert.fail("Missing signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ public void wrongSignature() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException {
+ final String serviceUrl = "https://localhost/pvp2/post";
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"));
+ payload.setIssueInstant(DateTime.now());
+ final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload);
+ final Marshaller marshaller = Constraint.isNotNull(
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped),
+ "SOAP Envelope marshaller not available");
+ final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream();
+ SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut);
+ httpReq.setMethod("POST");
+ httpReq.setContentType("text/xml");
+ httpReq.setContent(arrayOut.toByteArray());
+
+
+ try {
+ bindingImpl.decode(httpReq, httpResp, metadataProvider,
+ SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+ Assert.fail("Missing signature not detected");
+
+ } catch (final Pvp2Exception e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ public void validSignature() throws Pvp2Exception, MarshallingException, XMLParserException,
+ UnmarshallingException, CredentialsNotAvailableException {
+ final String serviceUrl = "https://localhost/pvp2/post";
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+ final URIComparator comparator = new EaafUriCompare(serviceUrl);
+
+ final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"));
+ payload.setIssueInstant(DateTime.now());
+ final RequestAbstractType signedPayload = Saml2Utils.signSamlObject(
+ payload, credentialProvider.getMetaDataSigningCredential(), true);
+
+ final Envelope enveloped = Saml2Utils.buildSoap11Envelope(signedPayload);
+ final Marshaller marshaller = Constraint.isNotNull(
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped),
+ "SOAP Envelope marshaller not available");
+ final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream();
+ SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut);
+ httpReq.setMethod("POST");
+ httpReq.setContentType("text/xml");
+ httpReq.setContent(arrayOut.toByteArray());
+
+
+ final InboundMessageInterface msg =
+ bindingImpl.decode(httpReq, httpResp, metadataProvider,
+ SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator);
+
+ Assert.assertNotNull("Inbound msg is null", msg);
+ Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage());
+ Assert.assertNotNull("EntityId is null", msg.getEntityID());
+ Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID());
+ Assert.assertTrue("Wrong isVerified flag", msg.isVerified());
+
+ }
+
+ @Test
+ public void encodeResponse() throws XMLParserException, UnmarshallingException,
+ Pvp2Exception, CredentialsNotAvailableException, UnsupportedEncodingException {
+ final String serviceUrl = "http://testservice.org";
+
+ final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml"));
+
+ bindingImpl.encodeResponse(httpReq, httpResp, response, serviceUrl, null,
+ credentialProvider.getMetaDataSigningCredential(), pendingReq);
+
+ Assert.assertEquals("http StatusCode", 200, httpResp.getStatus());
+ Assert.assertNotNull("PVP msg is null", httpResp.getContentLength());
+
+ Assert.assertEquals("ContentType", "text/xml", httpResp.getContentType());
+ Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String http = httpResp.getContentAsString();
+ Assert.assertNotNull("http body is null", http);
+ Assert.assertFalse("http body is empty", http.isEmpty());
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java
new file mode 100644
index 00000000..7418e1b3
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java
@@ -0,0 +1,93 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.dummy;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class DummyCredentialProvider extends AbstractCredentialProvider {
+
+ @Autowired IConfiguration basicConfig;
+
+ public static final String KEYSTORE_TYPE = "keystore.type";
+ public static final String KEYSTORE_PATH = "keystore.path";
+ public static final String KEYSTORE_PASSWORD = "keystore.pass";
+ public static final String KEYSTORE_NAME = "keystore.name";
+
+
+ public static final String KEY_METADATA_ALIAS = "key.metadata.alias";
+ public static final String KEY_METADATA_PASSWORD = "key.metadata.pass";
+
+ public static final String KEY_SIGNING_ALIAS = "key.sig.alias";
+ public static final String KEY_SIGNING_PASSWORD = "key.sig.pass";
+
+ public static final String KEY_ENCRYPTION_ALIAS = "key.enc.alias";
+ public static final String KEY_ENCRYPTION_PASSWORD = "key.enc.pass";
+
+ private static final String KEYSTORENAME = "jUnit test credential provider";
+
+ @Override
+ public KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException {
+ final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration();
+ keyStoreConfig.setFriendlyName(KEYSTORENAME);
+ keyStoreConfig.setKeyStoreType(getKeyStoreType());
+
+ keyStoreConfig.setKeyStoreName(
+ basicConfig.getBasicConfiguration(KEYSTORE_NAME));
+
+ keyStoreConfig.setSoftKeyStoreFilePath(getKeyStoreFilePath());
+ keyStoreConfig.setSoftKeyStorePassword(getKeyStorePassword());
+
+ return keyStoreConfig;
+ }
+
+ public String getKeyStoreType() {
+ return basicConfig.getBasicConfiguration(KEYSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType());
+
+ }
+
+ public String getKeyStoreFilePath() {
+ final String path = basicConfig.getBasicConfiguration(KEYSTORE_PATH);
+ return path;
+
+ }
+
+ public String getKeyStorePassword() {
+ return basicConfig.getBasicConfiguration(KEYSTORE_PASSWORD);
+ }
+
+ @Override
+ public String getMetadataKeyAlias() {
+ return basicConfig.getBasicConfiguration(KEY_METADATA_ALIAS);
+ }
+
+ @Override
+ public String getMetadataKeyPassword() {
+ return basicConfig.getBasicConfiguration(KEY_METADATA_PASSWORD);
+ }
+
+ @Override
+ public String getSignatureKeyAlias() {
+ return basicConfig.getBasicConfiguration(KEY_SIGNING_ALIAS);
+ }
+
+ @Override
+ public String getSignatureKeyPassword() {
+ return basicConfig.getBasicConfiguration(KEY_SIGNING_PASSWORD);
+ }
+
+ @Override
+ public String getEncryptionKeyAlias() {
+ return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_ALIAS);
+ }
+
+ @Override
+ public String getEncryptionKeyPassword() {
+ return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_PASSWORD);
+ }
+
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/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..6abe52dc
--- /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,167 @@
+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",
+ "/spring/eaaf_utils.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
new file mode 100644
index 00000000..0f8817a0
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java
@@ -0,0 +1,301 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.metadata;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.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 org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.metadata.ContactPerson;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.Organization;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.xmlsec.signature.support.SignatureException;
+import org.opensaml.xmlsec.signature.support.SignatureValidator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+
+
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml",
+ "/spring/test_eaaf_core_spring_config.beans.xml",
+ "/spring/eaaf_utils.beans.xml" })
+@TestPropertySource(locations = { "/config/config_1.props" })
+public class MetadataBuilderTest {
+
+ @Autowired private PvpMetadataBuilder metadataBuilder;
+ @Autowired private DummyCredentialProvider credentialProvider;
+
+ private static CertificateFactory fact;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ fact = CertificateFactory.getInstance("X.509");
+ }
+
+ @Test
+ public void buildIdpMetadata() throws CredentialsNotAvailableException, EaafException,
+ SecurityException, TransformerFactoryConfigurationError, MarshallingException,
+ TransformerException, ParserConfigurationException, IOException, SignatureException,
+ XMLParserException, UnmarshallingException, CertificateException {
+
+ final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, false, true);
+
+ //generate metadata
+ final String metadata = metadataBuilder.buildPvpMetadata(config);
+
+ //validate
+ final EntityDescriptor entity = validateMetadata(metadata);
+ Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS));
+ Assert.assertNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS));
+
+ }
+
+ @Test
+ public void buildSpMetadata() throws CredentialsNotAvailableException, EaafException,
+ SecurityException, TransformerFactoryConfigurationError, MarshallingException,
+ TransformerException, ParserConfigurationException, IOException, SignatureException,
+ XMLParserException, UnmarshallingException, CertificateException {
+
+ final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, false);
+
+ //generate metadata
+ final String metadata = metadataBuilder.buildPvpMetadata(config);
+
+ //validate
+ final EntityDescriptor entity = validateMetadata(metadata);
+ Assert.assertNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS));
+ Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS));
+
+ }
+
+ @Test
+ public void buildSpAndIdpMetadata() throws CredentialsNotAvailableException, EaafException,
+ SecurityException, TransformerFactoryConfigurationError, MarshallingException,
+ TransformerException, ParserConfigurationException, IOException, SignatureException,
+ XMLParserException, UnmarshallingException, CertificateException {
+
+ final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, true);
+
+ //generate metadata
+ final String metadata = metadataBuilder.buildPvpMetadata(config);
+
+ //validate
+ final EntityDescriptor entity = validateMetadata(metadata);
+ Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS));
+ Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS));
+
+ }
+
+ private EntityDescriptor validateMetadata(String metadata) throws UnsupportedEncodingException,
+ XMLParserException, UnmarshallingException, SignatureException, CertificateException {
+ Assert.assertNotNull("Metadata is null", metadata);
+ Assert.assertFalse("Metadata is empty", metadata.isEmpty());
+
+ final EntityDescriptor entity = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ new ByteArrayInputStream(metadata.getBytes("UTF-8")));
+
+ Assert.assertNotNull("Unmarshalling failed", entity);
+ Assert.assertNotNull("EntityId is null", entity.getEntityID());
+
+ Assert.assertNotNull("Signature is null", entity.getSignature());
+ final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator();
+ sigValidator.validate(entity.getSignature());
+
+ final Credential cred = new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")));
+ SignatureValidator.validate(entity.getSignature(), cred);
+
+ return entity;
+ }
+
+ public static IPvpMetadataBuilderConfiguration idpMetadataConfig(IPvp2CredentialProvider credentialProvider, boolean buildSpInfos, boolean buildIdpInfos) {
+ return new IPvpMetadataBuilderConfiguration() {
+
+ @Override
+ public boolean wantAuthnRequestSigned() {
+ return true;
+ }
+
+ @Override
+ public boolean wantAssertionSigned() {
+ return true;
+ }
+
+ @Override
+ public String getSpSloSoapBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+
+ }
+
+ @Override
+ public String getSpSloRedirectBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+
+ }
+
+ @Override
+ public String getSpSloPostBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public Collection<RequestedAttribute> getSpRequiredAttributes() {
+ return null;
+ }
+
+ @Override
+ public String getSpNameForLogging() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public String getSpAssertionConsumerServiceRedirectBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public String getSpAssertionConsumerServicePostBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public List<String> getSpAllowedNameIdTypes() {
+ return Arrays.asList(NameIDType.PERSISTENT);
+ }
+
+ @Override
+ public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException {
+ return credentialProvider.getMessageSigningCredential();
+ }
+
+ @Override
+ public Organization getOrgansiationInformation() {
+ return null;
+ }
+
+ @Override
+ public int getMetadataValidUntil() {
+ return 10;
+ }
+
+ @Override
+ public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException {
+ return credentialProvider.getMetaDataSigningCredential();
+ }
+
+ @Override
+ public String getIdpWebSsoRedirectBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public String getIdpWebSsoPostBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public String getIdpSloRedirectBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public String getIdpSloPostBindingUrl() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public List<String> getIdpPossibleNameIdTypes() {
+ return Arrays.asList(NameIDType.PERSISTENT);
+ }
+
+ @Override
+ public List<Attribute> getIdpPossibleAttributes() {
+ return null;
+ }
+
+ @Override
+ public String getEntityID() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public String getEntityFriendlyName() {
+ return RandomStringUtils.randomAlphabetic(10);
+ }
+
+ @Override
+ public Credential getEncryptionCredentials() throws CredentialsNotAvailableException {
+ return credentialProvider.getMessageSigningCredential();
+ }
+
+ @Override
+ public List<ContactPerson> getContactPersonInformation() {
+ return null;
+ }
+
+ @Override
+ public boolean buildSpSsoDescriptor() {
+ return buildSpInfos;
+ }
+
+ @Override
+ public boolean buildIdpSsoDescriptor() {
+ return buildIdpInfos;
+ }
+
+ @Override
+ public boolean buildEntitiesDescriptorAsRootElement() {
+ return false;
+ }
+ };
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java
new file mode 100644
index 00000000..accdd8b0
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java
@@ -0,0 +1,742 @@
+package at.gv.egiz.eaaf.modules.pvp2.test.metadata;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.transform.TransformerException;
+
+import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PvpEntityCategoryFilter;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter;
+import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.joda.time.DateTime;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.config.ConfigurationService;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.criterion.EntityRoleCriterion;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain;
+import org.opensaml.saml.metadata.resolver.filter.impl.RequiredValidUntilFilter;
+import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.security.impl.MetadataCredentialResolver;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.criteria.UsageCriterion;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.xmlsec.SignatureValidationConfiguration;
+import org.opensaml.xmlsec.SignatureValidationParameters;
+import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider;
+import org.opensaml.xmlsec.signature.support.SignatureValidationParametersCriterion;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+import net.shibboleth.utilities.java.support.xml.SerializeSupport;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+import okhttp3.HttpUrl;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml",
+ "/spring/test_eaaf_core_spring_config.beans.xml",
+ "/spring/eaaf_utils.beans.xml" })
+@TestPropertySource(locations = { "/config/config_1.props" })
+public class MetadataResolverTest {
+
+ private static MockWebServer mockWebServer;
+ private static HttpUrl mockServerUrl;
+
+ @Autowired
+ private PvpMetadataResolverFactory metadataResolverFactory;
+ @Autowired
+ private IHttpClientFactory httpClientFactory;
+ @Autowired private DummyCredentialProvider credentialProvider;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+ mockWebServer = new MockWebServer();
+ mockServerUrl = mockWebServer.url("/sp/metadata");
+
+ }
+
+ /**
+ * Single test initializer.
+ *
+ */
+ @Before
+ public void testInitializer() {
+
+ }
+
+ @Test
+ public void wrongSchema() {
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_schema.xml",
+ filterChain, "jUnit test", null);
+ Assert.fail("Wrong XML Schema not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong ErrorCode", "internal.pvp.08", e.getErrorId());
+ Assert.assertNotNull("params null", e.getParams());
+ Assert.assertEquals("Params size", 2, e.getParams().length);
+ Assert.assertEquals("Param[0] wrong",
+ "classpath:/data/pvp_metadata_wrong_schema.xml", e.getParams()[0]);
+
+ }
+
+ }
+
+ @Test
+ public void simpleClasspathMetadataWithoutSigValidation()
+ throws Pvp2MetadataException, ComponentInitializationException, ResolverException,
+ Pvp2InternalErrorException {
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_wrong_sig.xml",
+ filterChain, "jUnit test", null);
+
+ final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor(
+ "https://demo.egiz.gv.at/notExtist/");
+ Assert.assertNull("No EntityDescripter", entityIdNotExists);
+
+ final EntityDescriptor entityId = mdResolver.getEntityDescriptor(
+ "https://demo.egiz.gv.at/demoportal_demologin/");
+ Assert.assertNotNull("No EntityDescripter", entityId);
+
+ Assert.assertNotNull("Metadata provider is null", mdResolver);
+ final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver);
+
+ final CriteriaSet criteriaSet = new CriteriaSet();
+ criteriaSet.add(new EntityIdCriterion("https://demo.egiz.gv.at/demoportal_demologin/"));
+ criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
+ criteriaSet.add(new UsageCriterion(UsageType.SIGNING));
+ final SignatureValidationParameters sigValCrit = new SignatureValidationParameters();
+ sigValCrit.setBlacklistedAlgorithms(
+ ConfigurationService.get(SignatureValidationConfiguration.class)
+ .getBlacklistedAlgorithms());
+ sigValCrit.setSignatureTrustEngine(
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver));
+ criteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit));
+
+ final Iterable<Credential> keyInfos = resolver.resolve(criteriaSet);
+ Assert.assertNotNull("KeyInfos null", keyInfos);
+
+ }
+
+ @Test
+ public void noCredentials() {
+ final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml";
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ metadataUrl));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ metadataUrl,
+ filterChain, "jUnit test", null);
+ Assert.fail("Untrusted signature not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId());
+
+ }
+
+ }
+
+ @Test
+ public void wrongCredentials() throws CertificateException {
+ final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml";
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+ final CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ final BasicX509Credential credential = new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")));
+ credentials.add(credential);
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ metadataUrl));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ metadataUrl,
+ filterChain, "jUnit test", null);
+ Assert.fail("Untrusted signature not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId());
+
+ }
+
+ }
+
+ @Test
+ public void validCredentialsInvalidSig() throws CertificateException, Pvp2MetadataException,
+ ResolverException {
+ final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml";
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+ final CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt"))));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ metadataUrl));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ metadataUrl,
+ filterChain, "jUnit test", null);
+ Assert.fail("Untrusted signature not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId());
+
+ }
+
+ }
+
+ @Test
+ public void metadataSignatureValidCredentials() throws CertificateException, Pvp2MetadataException,
+ ResolverException, XMLParserException, UnmarshallingException, SamlSigningException,
+ CredentialsNotAvailableException, MarshallingException, TransformerException, IOException {
+
+ mockWebServer.shutdown();
+ mockWebServer = new MockWebServer();
+ mockServerUrl = mockWebServer.url("/sp/metadata");
+
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_moaid_test.xml"));
+ metadata.setValidUntil(DateTime.now().plusDays(1));
+ metadata.setSignature(null);
+ metadata.setEntityID(RandomStringUtils.randomAlphabetic(10));
+ final EntityDescriptor signedMatadata =
+ Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true);
+ final Element metadataElement = XMLObjectSupport.marshall(signedMatadata);
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(SerializeSupport.nodeToString(metadataElement))
+ .setHeader("Content-Type", "text/html;charset=utf-8"));
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+ final CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ mockServerUrl.url().toString()));
+ filterList.add(new PvpEntityCategoryFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+
+ final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor(
+ metadata.getEntityID());
+ Assert.assertNotNull("No EntityDescripter", entityIdNotExists);
+
+ }
+
+ @Test
+ public void metadataSignatureValidCredentialsSecond() throws CertificateException, Pvp2MetadataException,
+ ResolverException, XMLParserException, UnmarshallingException, SamlSigningException,
+ CredentialsNotAvailableException, MarshallingException, TransformerException, IOException {
+
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory.xml"));
+ metadata.setValidUntil(DateTime.now().plusDays(1));
+ metadata.setSignature(null);
+ metadata.setEntityID(RandomStringUtils.randomAlphabetic(10));
+ final EntityDescriptor signedMatadata =
+ Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true);
+ final Element metadataElement = XMLObjectSupport.marshall(signedMatadata);
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(SerializeSupport.nodeToString(metadataElement))
+ .setHeader("Content-Type", "text/html;charset=utf-8"));
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+ final CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ mockServerUrl.url().toString()));
+ filterList.add(new PvpEntityCategoryFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+
+
+
+ final EntityDescriptor descr = mdResolver.getEntityDescriptor(metadata.getEntityID());
+ Assert.assertNotNull("No EntityDescripter", descr);
+
+ final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS)
+ .getAttributeConsumingServices().get(0).getRequestAttributes();
+ Assert.assertNotNull("Req. attributes are null", reqAttr);
+ Assert.assertEquals("# of req. attributes", 20, reqAttr.size());
+
+ }
+
+ @Test
+ public void metadataSignatureValidCredentialsThird() throws CertificateException, Pvp2MetadataException,
+ ResolverException, XMLParserException, UnmarshallingException, SamlSigningException,
+ CredentialsNotAvailableException, MarshallingException, TransformerException, IOException {
+
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory_egov.xml"));
+ metadata.setValidUntil(DateTime.now().plusDays(1));
+ metadata.setSignature(null);
+ metadata.setEntityID(RandomStringUtils.randomAlphabetic(10));
+ final EntityDescriptor signedMatadata =
+ Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true);
+ final Element metadataElement = XMLObjectSupport.marshall(signedMatadata);
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(SerializeSupport.nodeToString(metadataElement))
+ .setHeader("Content-Type", "text/html;charset=utf-8"));
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+ final CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ mockServerUrl.url().toString()));
+ filterList.add(new PvpEntityCategoryFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+
+
+
+ final EntityDescriptor descr = mdResolver.getEntityDescriptor(metadata.getEntityID());
+ Assert.assertNotNull("No EntityDescripter", descr);
+
+ final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS)
+ .getAttributeConsumingServices().get(0).getRequestAttributes();
+ Assert.assertNotNull("Req. attributes are null", reqAttr);
+ Assert.assertEquals("# of req. attributes", 9, reqAttr.size());
+
+ }
+
+ @Test
+ public void metadataExpired() throws CertificateException, Pvp2MetadataException,
+ ResolverException, XMLParserException, UnmarshallingException, SamlSigningException,
+ CredentialsNotAvailableException, MarshallingException, TransformerException, IOException {
+
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid.xml"));
+ metadata.setValidUntil(DateTime.now().minusDays(2));
+ metadata.setSignature(null);
+ Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true);
+ final Element metadataElement = XMLObjectSupport.marshall(metadata);
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(SerializeSupport.nodeToString(metadataElement))
+ .setHeader("Content-Type", "text/html;charset=utf-8"));
+
+ final List<BasicX509Credential> credentials = new ArrayList<>();
+ final CertificateFactory fact = CertificateFactory.getInstance("X.509");
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))));
+ credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate(
+ MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ credentials,
+ mockServerUrl.url().toString()));
+ filterList.add(new RequiredValidUntilFilter());
+ filterList.add(new PvpEntityCategoryFilter(false));
+
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+ Assert.fail("Expired metadata not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId());
+
+ }
+
+
+ }
+
+ @Test
+ public void simpleClasspathMetadataWithoutSigValidationMoaidTwoSigKeys()
+ throws Pvp2MetadataException, ComponentInitializationException, ResolverException,
+ Pvp2InternalErrorException {
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata";
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_moaid_test.xml",
+ filterChain, "jUnit test", null);
+
+ final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor(
+ "https://demo.egiz.gv.at/notExtist/");
+ Assert.assertNull("No EntityDescripter", entityIdNotExists);
+
+ final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve);
+ Assert.assertNotNull("No EntityDescripter", entityId);
+
+ Assert.assertNotNull("Metadata provider is null", mdResolver);
+ final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver);
+
+ final CriteriaSet sigCriteriaSet = new CriteriaSet();
+ sigCriteriaSet.add(new EntityIdCriterion(entityIdToResolve));
+ sigCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
+ sigCriteriaSet.add(new UsageCriterion(UsageType.SIGNING));
+ final SignatureValidationParameters sigValCrit = new SignatureValidationParameters();
+ sigValCrit.setBlacklistedAlgorithms(
+ ConfigurationService.get(SignatureValidationConfiguration.class)
+ .getBlacklistedAlgorithms());
+ sigValCrit.setSignatureTrustEngine(
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver));
+ sigCriteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit));
+
+ final Iterable<Credential> singingKeyInfos = resolver.resolve(sigCriteriaSet);
+ Assert.assertNotNull("Signing KeyInfos null", singingKeyInfos);
+ Assert.assertTrue("First Credential resolved", singingKeyInfos.iterator().hasNext());
+ Assert.assertTrue("Second Credential resolved", singingKeyInfos.iterator().hasNext());
+
+ final CriteriaSet encCriteriaSet = new CriteriaSet();
+ encCriteriaSet.add(new EntityIdCriterion(entityIdToResolve));
+ encCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
+ encCriteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION));
+ final Iterable<Credential> encKeyInfos = resolver.resolve(encCriteriaSet);
+ Assert.assertNotNull("Encryption KeyInfos null", encKeyInfos);
+ Assert.assertTrue("No Credential resolved", encKeyInfos.iterator().hasNext());
+
+ }
+
+ @Test
+ public void httpMetadataLoading() throws UnsupportedEncodingException,
+ IOException, ResolverException, Pvp2MetadataException {
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_moaid_test.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata";
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+
+ final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor(
+ "https://demo.egiz.gv.at/notExtist/");
+ Assert.assertNull("No EntityDescripter", entityIdNotExists);
+
+ final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve);
+ Assert.assertNotNull("No EntityDescripter", entityId);
+
+ }
+
+ @Test
+ public void httpMetadataLoadingRefeshFailed() throws UnsupportedEncodingException,
+ IOException, ResolverException, Pvp2MetadataException {
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_moaid_test.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata";
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+
+ final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor(
+ "https://demo.egiz.gv.at/notExtist/");
+ Assert.assertNull("No EntityDescripter", entityIdNotExists);
+
+ final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve);
+ Assert.assertNotNull("No EntityDescripter", entityId);
+
+ final DateTime lastRefreshSucess = mdResolver.getLastSuccessfulRefresh();
+
+ try {
+ mdResolver.refresh();
+ Assert.fail("Refesh possible without available metadata");
+
+ } catch (final ResolverException e) {
+ Assert.assertFalse("Wrong Refesh success flag", mdResolver.wasLastRefreshSuccess());
+ Assert.assertEquals("Wrong refresh success date", lastRefreshSucess, mdResolver
+ .getLastSuccessfulRefresh());
+
+ }
+
+ }
+
+ @Test
+ public void httpMetadataLoadingWithRefeshSuccess() throws UnsupportedEncodingException,
+ IOException, ResolverException, Pvp2MetadataException {
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_moaid_test.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_moaid_test.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata";
+
+ final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+
+ final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor(
+ "https://demo.egiz.gv.at/notExtist/");
+ Assert.assertNull("No EntityDescripter", entityIdNotExists);
+
+ final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve);
+ Assert.assertNotNull("No EntityDescripter", entityId);
+
+ // refresh metadata
+ mdResolver.refresh();
+
+ Assert.assertTrue("Refresh not sucessful", mdResolver.wasLastRefreshSuccess());
+
+ }
+
+ @Test
+ public void httpMetadataLoadingWithoutHttpClient() throws UnsupportedEncodingException,
+ IOException, ResolverException, Pvp2MetadataException {
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_moaid_test.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ mockServerUrl.url().toString(),
+ filterChain, "jUnit test", null);
+ Assert.fail("No httpclient not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId());
+ Assert.assertNotNull("No error params", e.getParams());
+ Assert.assertEquals("Wrong params size", 2, e.getParams().length);
+
+ }
+ }
+
+ @Test
+ public void httpMetadataLoadingWrongUrl() throws UnsupportedEncodingException,
+ IOException, ResolverException, Pvp2MetadataException {
+
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(new String(IOUtils.toByteArray(
+ MetadataResolverTest.class.getResourceAsStream(
+ "/data/pvp_metadata_moaid_test.xml")), "UTF-8"))
+ .setHeader("Content-Type", "text/xml"));
+
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+
+ final MetadataFilterChain filterChain = new MetadataFilterChain();
+ filterChain.setFilters(filterList);
+
+ try {
+ metadataResolverFactory.createMetadataProvider(
+ "http://127.0.0.1/notexist",
+ filterChain, "jUnit test", httpClientFactory.getHttpClient());
+ Assert.fail("No httpclient not detected");
+
+ } catch (final Pvp2MetadataException e) {
+ Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId());
+ Assert.assertNotNull("No error params", e.getParams());
+ Assert.assertEquals("Wrong params size", 2, e.getParams().length);
+
+ }
+
+ }
+
+ private MetadataCredentialResolver createKeyInfoResolver(IPvp2MetadataProvider mdResolver)
+ throws ComponentInitializationException {
+ final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>();
+ keyInfoProvider.add(new DSAKeyValueProvider());
+ keyInfoProvider.add(new RSAKeyValueProvider());
+ keyInfoProvider.add(new InlineX509DataProvider());
+ final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver(
+ keyInfoProvider);
+
+ final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver(
+ mdResolver);
+ roleDescriptorResolver.setRequireValidMetadata(true);
+ roleDescriptorResolver.initialize();
+
+ final MetadataCredentialResolver resolver = new MetadataCredentialResolver();
+ resolver.setRoleDescriptorResolver(roleDescriptorResolver);
+ resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver);
+ resolver.initialize();
+
+ return resolver;
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props
new file mode 100644
index 00000000..6177b738
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props
@@ -0,0 +1,19 @@
+security.hsmfacade.host=eid.a-sit.at
+security.hsmfacade.port=9050
+security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt
+security.hsmfacade.username=authhandler-junit
+security.hsmfacade.password=supersecret123
+security.hsmfacade.hsmname=software
+
+keystore.path=classpath:/data/junit.jks
+keystore.pass=password
+key.metadata.alias=meta
+key.metadata.pass=password
+key.sig.alias=sig
+key.sig.pass=password
+key.enc.alias=
+key.enc.pass=
+
+client.http.connection.timeout.socket=2
+client.http.connection.timeout.connection=2
+client.http.connection.timeout.request=2 \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props
new file mode 100644
index 00000000..60cecebb
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props
@@ -0,0 +1,12 @@
+keystore.path=classpath:/data/junit.jks
+keystore.pass=password
+key.metadata.alias=shibboleth-sign
+key.metadata.pass=password
+key.sig.alias=shibboleth-sign
+key.sig.pass=password
+key.enc.alias=
+key.enc.pass=
+
+client.http.connection.timeout.socket=2
+client.http.connection.timeout.connection=2
+client.http.connection.timeout.request=2 \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props
new file mode 100644
index 00000000..abc8f591
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props
@@ -0,0 +1,18 @@
+security.hsmfacade.host=eid.a-sit.at
+security.hsmfacade.port=9050
+security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt
+security.hsmfacade.username=authhandler-junit
+security.hsmfacade.password=supersecret123
+security.hsmfacade.hsmname=software
+
+keystore.type=hsmfacade
+keystore.name=authhandler
+key.metadata.alias=authhandler-sign
+key.sig.alias=authhandler-sign
+key.sig.pass=password
+key.enc.alias=
+key.enc.pass=
+
+client.http.connection.timeout.socket=2
+client.http.connection.timeout.connection=2
+client.http.connection.timeout.request=2 \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/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_with_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml
new file mode 100644
index 00000000..f9de11c4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <ds:Reference URI="#_aeebfae3ce681fe3ddcaf213a42f01d3">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <ds:DigestValue>sBVJQf9b+QIxRfH8YuTbF6hBrf4=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>JK68H5XqmD2OEA8O/UCZFenVj0TrvauPhaKJt73pbHbi//hO1hBcRQbV2Qg3gQ11EcJ9Q+TM3TCe9nT6tdU/z7ry3qdZvlOfrkMF13fY4HOIuvB9AcySdxq2yKA3V5O9sLhf5S9qCyx9lMnTARC7wkVs4j2Pv00R6P/iROOHD5ryGF2J0FdtMp9VqhvQJ9yRGM2lTduF98MqxWA2EMk6AMo7qij0Bvha1B2OyFSU9HM3fyfRQpXDeiLnKHcjLpzu5TDNkKrP75c7vv85DDr7s2I0p74nAOVLMuLau5tEQ91Crk9QoqoqqEecKWcNJDXTO9MahCQw77hUDL1WOEMFFg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4
+pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T
+iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq
++TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU
+cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ==</ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID>
+ </saml2:Subject>
+ <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
+ <saml2p:RequestedAuthnContext>
+ <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2p:RequestedAuthnContext>
+</saml2p:AuthnRequest>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml
new file mode 100644
index 00000000..ef35ea92
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer>
+ <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID>
+ </saml2:Subject>
+ <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
+ <saml2p:RequestedAuthnContext>
+ <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2p:RequestedAuthnContext>
+</saml2p:AuthnRequest>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/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/AuthRequest_withsig_expired.b64 b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64
new file mode 100644
index 00000000..f02ce2ea
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64
@@ -0,0 +1 @@
+PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlSW5kZXg9IjAiIERlc3RpbmF0aW9uPSJodHRwczovL2VpZGFzLXRlc3QuYm1pLmd2LmF0L21zX2Nvbm5lY3Rvci9wdnAvcG9zdCIgSUQ9Il9lZDJjZDQ0NjNiODJkYzYwOTI0MzM5YjEwZWIyNzQ4OCIgSXNQYXNzaXZlPSJmYWxzZSIgSXNzdWVJbnN0YW50PSIyMDIwLTAyLTA0VDA2OjQ4OjU4LjA3NFoiIFByb3ZpZGVyTmFtZT0iT3BlbklEIENvbm5lY3QgRGVtbyIgVmVyc2lvbj0iMi4wIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL2RlbW8uZWdpei5ndi5hdC9kZW1vcG9ydGFsX21vYWlkLTIuMC9zcC9laWRhcy9tZXRhZGF0YTwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI19lZDJjZDQ0NjNiODJkYzYwOTI0MzM5YjEwZWIyNzQ4OCI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PGVjOkluY2x1c2l2ZU5hbWVzcGFjZXMgeG1sbnM6ZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgUHJlZml4TGlzdD0ieHMiLz48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxkczpEaWdlc3RWYWx1ZT5aSEZ0UVpYeXBTbFhrK3ZYdGZlSDVMWEdNcTE2MUpmUHdFUHBPVFhUSzlRPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5CSFFHeXpMZE5rb2dGZmt5T0FxVnBTRXh1NXhRaWxvVUs5L01GejBTM01LZnRkaDVtTXVaT0tBSUU1SUMrKzlPS25UbUlncUVNdWJVKzAvTEVobTUwUk1oZGtxYUFFWG02Y2xKYmlaOHBvT0pPd09sWlhQVWtub0J4NkZxRi9MNThqTFV6ZlluNEh0OUtCOGVQV2djU2FVR3lpMHB4OEdzMzNJUDd3eGF2bnhGYUMvSERpZkN0UytaZzJ5QVpJR2lnQksxcXIrUTMweWIrNWZEQmprU3pWMWJGb2NKdHY2cDJhSXlUMTNnb2x6N0FuK3JSWVloVnd5WENBY25CdHJjQTREbmNpWVVnTVNLQTRTR1hLNExyZ1RTdjFXUHJEdlJmWkVLMk9xL2JEMHE0MWF1T1d4VVkzK2x2T2pJYUI3YnRobURiSVJPbmhaWW1rMDlPSFZJMVE9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJREt6Q0NBaE1DQkZyeEtPNHdEUVlKS29aSWh2Y05BUUVMQlFBd1dqRUxNQWtHQTFVRUJoTUNRVlF4RFRBTEJnTlZCQW9NQkVWSApTVm94R0RBV0JnTlZCQXNNRDJSbGJXOHVaV2RwZWk1bmRpNWhkREVpTUNBR0ExVUVBd3daVFU5QkxVbEVJRWxFVUNBb1ZHVnpkQzFXClpYSnphVzl1S1RBZUZ3MHhPREExTURnd05ETTBOVFJhRncweU1UQXhNekV3TkRNME5UUmFNRm94Q3pBSkJnTlZCQVlUQWtGVU1RMHcKQ3dZRFZRUUtEQVJGUjBsYU1SZ3dGZ1lEVlFRTERBOWtaVzF2TG1WbmFYb3VaM1l1WVhReElqQWdCZ05WQkFNTUdVMVBRUzFKUkNCSgpSRkFnS0ZSbGMzUXRWbVZ5YzJsdmJpa3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDYUZucW9hWW9xClVwdGVuZW1DNkZpVkRnNUYyaEVqcGppeDgrb3c2LzZRaFVsMmNQT1MwdXdaSGFJdndUL1JWYko5Q1BkaWw2KzExcWFDUGZaK0ZvWSsKTStrZTdUUmQyUlMxRHFGYmUxS0MwaW1FbndlbXlMUXJZZTVQbTdETmNhWS9rSFRUcStrMGVlR2JZSDBVL0lvcHlpMFZ1TjVPV2w0RgpWZzQ1cGY3a25oWGthaW1JdGRqbkNYbktjWU05MW1tbHRDZjZURGdVcno3VVM3UG1ndmlubmhmQmdkSVRBVDRHUnI0ZWhsaVQrL2p0CjFPekhFeVdSSGFuQkdJcFhOZVpOcXhnbnBuR3RhRGg0Slp1WVI4cWZIK0dSSzZkdFcyemllajZyR0lpVUVsR1ZDa1hzb2hneE1OenEKbldlRDlKVDgreXlwMVhabHlRZitJeGhoRVNRTEFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUlGZWpBRlFlcGFFbC9rQwpWTHZpZE1SK01YcTVMQ0dIdGhVaUk2ZURUUVorSDdsWmRIbGo1NDdYd0VkWDE1YjZNZDNoN2VTSjRod2xmVjRnby8wRmFvTFB6dlZxCml0d3RZWTVodHl3QjNCNlpWMzRFeWk2QzU5R2wzNFhyVjhDV3hINEtLd0xzVkFqQXkrL3AvWGgwcTJwelNCa2VPQ2h6Qk1Ca2pteWMKMlVlNE1FS2RMOWd1enA2K1ljL0hML3BoSEFLWWFwa1Z5Rnd2c2RxV09neVJ6eEFISU5rbzhFeEltTU1CM3hCNWE1MmtmcUxjdWk1TwpmekVoandMRkphR0JNbUZDbUZHR09Vd3RJdmwvNlpRMkxMek9FOStnaVZLOVdzSWdIMTFQdStlalBGQWJYZjhjZjRvV2hiQWZUa2l5CjRqcFhycDc3SlhGUlNEV2RkYjB5ZVBjPTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sMnA6RXh0ZW5zaW9ucz48ZWlkOlJlcXVlc3RlZEF0dHJpYnV0ZXMgeG1sbnM6ZWlkPSJodHRwOi8vZWlkLmd2LmF0L2VJRC9hdHRyaWJ1dGVzL3NhbWwtZXh0ZW5zaW9ucyI+PGVpZDpSZXF1ZXN0ZWRBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJFSUQtU0VDVE9SLUZPUi1JREVOVElGSUVSIiBOYW1lPSJ1cm46b2lkOjEuMi40MC4wLjEwLjIuMS4xLjI2MS4zNCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiIGlzUmVxdWlyZWQ9InRydWUiPjxlaWQ6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+dXJuOnB1YmxpY2lkOmd2LmF0OmNkaWQrQkY8L2VpZDpBdHRyaWJ1dGVWYWx1ZT48L2VpZDpSZXF1ZXN0ZWRBdHRyaWJ1dGU+PC9laWQ6UmVxdWVzdGVkQXR0cmlidXRlcz48L3NhbWwycDpFeHRlbnNpb25zPjxzYW1sMnA6TmFtZUlEUG9saWN5IEFsbG93Q3JlYXRlPSJ0cnVlIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnBlcnNpc3RlbnQiLz48c2FtbDJwOlJlcXVlc3RlZEF1dGhuQ29udGV4dCBDb21wYXJpc29uPSJtaW5pbXVtIj48c2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWYgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHA6Ly9laWRhcy5ldXJvcGEuZXUvTG9BL2xvdzwvc2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PC9zYW1sMnA6UmVxdWVzdGVkQXV0aG5Db250ZXh0PjxzYW1sMnA6U2NvcGluZz48c2FtbDJwOlJlcXVlc3RlcklEPmh0dHBzOi8vZGVtby5lZ2l6Lmd2LmF0L2RlbW9wb3J0YWwtb3BlbklEX2RlbW88L3NhbWwycDpSZXF1ZXN0ZXJJRD48L3NhbWwycDpTY29waW5nPjwvc2FtbDJwOkF1dGhuUmVxdWVzdD4 \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml
new file mode 100644
index 00000000..2654f2e8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
+ </ds:Transform>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>fCE31ZeXZybQLOuNQBePLjFrCtKdvCmeyJ1tUW/ghtA=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>vUFR3YPk5wiBJnrLh6Er7V46FNDMuB5Jcu73Rw7tipgr+bnV0reRNcZ5TGT+VMjNhtKJMcqgjrQWJ6tACe1r0mzhpRSVQkw7yFkTvIhQHX1a08yqJ4yy3qiN13ctDo4VgP9qHUim7b797oOKNhRXFk+2GJA5hRcpRliUjhBlzTYrxpkY5NcYDRhDPlvMx+l11oa1iDGuAylN+ty4h3P4fIoIgL9Tz1m3l65LqkV5RBc6avSeHw9OASMigPsjd5b0IBvhvJ611xLgzC1BOtJshiw1k/p8alv8TaUmYZ/kJbRN1tuTBL129edbS0Rz0faT0tniF42QHteJ214brK3rCg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>xRE83dJy1dj+KVBp5Syo91fjGeG1MmJDSuTZ5MwdDzvIZrbK3YPh0jbJz4lOSrw9urRacavZX4m2
+XAKfSRxaowP3GqTh3Ew4WJE7yXEnWiic7bUz8uMIr020bsvqHCvY48+oPARbz/cEOf5NgMBWqo9E
+nibdIyU5+AmfFzDaMwNocJEANoXrjLTpduCHvT0Qt/wH+7rVdgjX1djMrBhyMWs7GQyIBRfuf58m
+8kdcoiMSm9AWA4d4GzXch+bi1QRzj+Ib80DeWdcXP3Hc6pcyp/+L+hya2jZ9NMS8yup6xuoAeh7w
+6JNpfE9QnO3/CPrDZTtmjPK2OIRkhgn4Yi+iBQ==</ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+ </saml2p:Status>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0">
+ <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <saml2:Subject>
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml
new file mode 100644
index 00000000..e6530cca
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" 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"/>
+ </saml2p:Status>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0">
+ <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <saml2:Subject>
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_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/assertion_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt
new file mode 100644
index 00000000..b53c558d
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN
+MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw
+HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN
+MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw
+WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC
+LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG
+SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh
+ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L
+-----END CERTIFICATE-----
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/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/hsm_facade_trust_root.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/hsm_facade_trust_root.crt
new file mode 100644
index 00000000..01be3821
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/hsm_facade_trust_root.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBdDCCARqgAwIBAgIEXkz1yjAKBggqhkjOPQQDAjARMQ8wDQYDVQQDDAZlY3Jv
+b3QwHhcNMjAwMjE5MDg0NjAyWhcNMjEwMjE4MDg0NjAyWjARMQ8wDQYDVQQDDAZl
+Y3Jvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS8yvpVIWbPj4E7Lr87hwQR
+T9DZf9WY5LMV7gF6NKpnJ5JkEql/s7fqBVbrh8aSNo6gmfmSk4VYGhPJ+DCMzzQj
+o2AwXjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFOXafzYpIOlu6BgNU+Ee
+JWuJobgWMB0GA1UdDgQWBBTl2n82KSDpbugYDVPhHiVriaG4FjALBgNVHQ8EBAMC
+AQYwCgYIKoZIzj0EAwIDSAAwRQIgRt/51PKL/bATuLCdib95Ika+h845Jo0G+Sbn
+bzNwJAcCIQCVD1cxEBuUkKaiaLbTiNVsEjvQb6ti0TFbbQUH66jCGA==
+-----END CERTIFICATE-----
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks
new file mode 100644
index 00000000..59e6ad13
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks
Binary files differ
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt
new file mode 100644
index 00000000..b544c194
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB
+VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk
+YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC
+QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh
+ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA
+O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H
+rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+
+WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7
+/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb
+f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l
+PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9
+YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX
+zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS
+YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW
+9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi
+purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==
+-----END CERTIFICATE-----
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jks
new file mode 100644
index 00000000..b5262cb8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jks
Binary files differ
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12 b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12
new file mode 100644
index 00000000..c3fe2681
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12
Binary files differ
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt
new file mode 100644
index 00000000..61aa137b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml
new file mode 100644
index 00000000..7fdbef90
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="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: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>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>
+ <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_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..7ccd5484
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml
@@ -0,0 +1,242 @@
+<?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:X509Data>
+ <ds:X509Certificate>MIIDFDCCArqgAwIBAgIIFy4Oe7D+zq8wCgYIKoZIzj0EAwIwIzEhMB8GA1UEAwwY
+S2V5c3RvcmVCYWNrZWRQa2lTZXJ2aWNlMB4XDTIwMDIxOTE0MDMxNVoXDTIwMDUx
+OTEzMDMxNVowMjEdMBsGA1UEAwwUaW50LWF1dGhoYW5kbGVyLXNpZ24xETAPBgNV
+BAoMCHNvZnR3YXJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtE1v
+1J54suM3VR17mTO5OKrCBeDP6a2dQswhMmUNO6i1l4eXNbtBvMj7k0mnc4yLLZxQ
+P0cosjT1kNkOvSNCQcSI+869EOdU4QDCreGLss9a84ZNf/X3ioq/2PYTLOJSMkDQ
+qLMHUVawwPYw+ZyUHaY7G0AwX5Gj1gMadfWVMDPAo5OT9WntpqG1850yO0aUMBaF
+GSE9RrWVmL1+d2qHqh/pAwq6DQEtbKCl18t1zQfLZvumnQfF930KB2IkLaq6wRTW
+IRdwte20PfVmEloAOdegXqUX59rkq6+5CaXfIsN+4Vkb12n2ArZwI/EFjgRdtGYj
+CmuySDorynSHrCO934/LHjZtdJPFbg5/4CTXpI1aInum4uqDuq6xoL+ns4hk8kkD
+9H9Pj5MYyjUc51+450ylOwLmGkqNDJBh3ecnH76NIoKviR3KlBaj0bSlnoV5Kl8H
+bfnXQD98BH+YLeULrD3XWVjirOWPdfdNKcInpuXrdTZ/GvyGL5T/63mtEWiWysfP
+Gw4+9AlWNXpyLviaHfxTpC6T76qYHKHd4eltRLubrgL8gHZrJwHio98kKfVMS3Oy
+qHAEWBSWv+LveARn0RF4jlcPIL3gclrU9jxF4k5Btvdax3+if1MWVAZ9ML5263ug
+Qr11Pkbko09VqppyM484/o+mJihTWyucKdVONw8CAwEAATAKBggqhkjOPQQDAgNI
+ADBFAiBJSZqfI1kmJGy8/tRut7h2YbZWNeUA+gmFX+wJxu9ePwIhALgjht8La4AZ
+/r3t33clJW8tGRMiA8cBbxm3Ox0y7DyP</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:X509Data>
+ <ds:X509Certificate>MIIDFDCCArqgAwIBAgIIFy4Oe7D+zq8wCgYIKoZIzj0EAwIwIzEhMB8GA1UEAwwY
+S2V5c3RvcmVCYWNrZWRQa2lTZXJ2aWNlMB4XDTIwMDIxOTE0MDMxNVoXDTIwMDUx
+OTEzMDMxNVowMjEdMBsGA1UEAwwUaW50LWF1dGhoYW5kbGVyLXNpZ24xETAPBgNV
+BAoMCHNvZnR3YXJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtE1v
+1J54suM3VR17mTO5OKrCBeDP6a2dQswhMmUNO6i1l4eXNbtBvMj7k0mnc4yLLZxQ
+P0cosjT1kNkOvSNCQcSI+869EOdU4QDCreGLss9a84ZNf/X3ioq/2PYTLOJSMkDQ
+qLMHUVawwPYw+ZyUHaY7G0AwX5Gj1gMadfWVMDPAo5OT9WntpqG1850yO0aUMBaF
+GSE9RrWVmL1+d2qHqh/pAwq6DQEtbKCl18t1zQfLZvumnQfF930KB2IkLaq6wRTW
+IRdwte20PfVmEloAOdegXqUX59rkq6+5CaXfIsN+4Vkb12n2ArZwI/EFjgRdtGYj
+CmuySDorynSHrCO934/LHjZtdJPFbg5/4CTXpI1aInum4uqDuq6xoL+ns4hk8kkD
+9H9Pj5MYyjUc51+450ylOwLmGkqNDJBh3ecnH76NIoKviR3KlBaj0bSlnoV5Kl8H
+bfnXQD98BH+YLeULrD3XWVjirOWPdfdNKcInpuXrdTZ/GvyGL5T/63mtEWiWysfP
+Gw4+9AlWNXpyLviaHfxTpC6T76qYHKHd4eltRLubrgL8gHZrJwHio98kKfVMS3Oy
+qHAEWBSWv+LveARn0RF4jlcPIL3gclrU9jxF4k5Btvdax3+if1MWVAZ9ML5263ug
+Qr11Pkbko09VqppyM484/o+mJihTWyucKdVONw8CAwEAATAKBggqhkjOPQQDAgNI
+ADBFAiBJSZqfI1kmJGy8/tRut7h2YbZWNeUA+gmFX+wJxu9ePwIhALgjht8La4AZ
+/r3t33clJW8tGRMiA8cBbxm3Ox0y7DyP</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/>
+ <md:AttributeConsumingService index="0" isDefault="true">
+ <md:ServiceName xml:lang="en">Default Service</md:ServiceName>
+ <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ </md:AttributeConsumingService>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml
new file mode 100644
index 00000000..ddc6e4ad
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata" validUntil="2040-02-05T06:41:42.966Z">
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#_2e23ca9b2ba4dc9eef15187830d07ff0">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor use="signing">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+ EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+ OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+ BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+ SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+ tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+ y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+ utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+ lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+ gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+ tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+ MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+ UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+ G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+ z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+ lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+ cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/>
+ <md:AttributeConsumingService index="0" isDefault="true">
+ <md:ServiceName xml:lang="en">Default Service</md:ServiceName>
+ <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ </md:AttributeConsumingService>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml
new file mode 100644
index 00000000..d5855d43
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#_ee52efc823faa4334d93d1a787fb2c24"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/><md:AttributeConsumingService index="0" isDefault="true"><md:ServiceName xml:lang="en">Default Service</md:ServiceName><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-FAMILY-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.80" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-CCS-URL" Name="urn:oid:1.2.40.0.10.2.1.1.261.64" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-PROF-REP-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.86" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.22" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-SIGNER-CERTIFICATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.66" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-PROF-REP-DESCRIPTION" Name="urn:oid:1.2.40.0.10.2.1.1.261.88" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.28" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-REFERENCE-VALUE" Name="urn:oid:1.2.40.0.10.2.1.1.261.90" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.72" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BPK" Name="urn:oid:1.2.40.0.10.2.1.1.261.98" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.73" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-GIVEN-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.78" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-E-ID-TOKEN" Name="urn:oid:1.2.40.0.10.2.1.1.261.39" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-IDENTITY-STATUS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.109" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/></md:AttributeConsumingService></md:SPSSODescriptor><md:Organization><md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName><md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName><md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL></md:Organization><md:ContactPerson contactType="technical"><md:Company>E-Government Innovationszentrum</md:Company><md:GivenName>Lenz</md:GivenName><md:SurName>Thomas</md:SurName><md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress><md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber></md:ContactPerson></md:EntityDescriptor> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml
new file mode 100644
index 00000000..54ad2b03
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z">
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#_ee52efc823faa4334d93d1a787fb2c24">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <md:Extensions>
+ <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
+ <saml2:Attribute xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken</saml2:AttributeValue>
+ </saml2:Attribute>
+ </mdattr:EntityAttributes>
+ </md:Extensions>
+ <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor use="signing">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/>
+ <md:AttributeConsumingService index="0" isDefault="true">
+ <md:ServiceName xml:lang="en">Default Service</md:ServiceName>
+ <md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ </md:AttributeConsumingService>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml
new file mode 100644
index 00000000..5129c494
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="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#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#_ee52efc823faa4334d93d1a787fb2c24">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <md:Extensions>
+ <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
+ <saml2:Attribute xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken</saml2:AttributeValue>
+ </saml2:Attribute>
+ </mdattr:EntityAttributes>
+ </md:Extensions>
+ <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor use="signing">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/>
+ <md:AttributeConsumingService index="0" isDefault="true">
+ <md:ServiceName xml:lang="en">Default Service</md:ServiceName>
+ <md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ </md:AttributeConsumingService>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml
new file mode 100644
index 00000000..5fc61717
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml
@@ -0,0 +1,122 @@
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2059-07-27T11:23:29.736Z">
+ <ds:Signature>
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#_c0303e3081ac29bb8329cade76279069">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>IjxuoZphYVmZdZ5HfoVDr35r2b1V840+SMeC89IO/SQ=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>JILQKKPvsK7onsMweJauAcGEniFGJ5bXEOvfYhxAYCB+dXL6pH87USD1v9UqycllBDqQE/Rp2tPtqo11CjdcKs0KkceQCZjzmDlVPqMZrgh0FerTSysF0fcPKoKeAtqqk+WSu7Xk9lU+PCxGArGA+vBLTRRbAOuZpE7ORrS7AF2m5uaO1YOKfO0GN+LoxTiygI2aeqKsKMlPkboh4ZuEjv1ht9xUHeQtAf/MHtaXZDvaRQPXALf0oCRnDWpiiqvKdARJq5NXrrbrdow/M1FpoddtE0Mu65AsorIdXoPSXJnLhw/zDfHv82PQo0pW7ujc0yJY+5VzfURMZOyKmrfCmg==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor use="signing">
+ <ds:KeyInfo>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4
+pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T
+iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq
++TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU
+cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ==</ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ </ds:KeyInfo>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect"/>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" index="1"/>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml
new file mode 100644
index 00000000..510c84f8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor
+ xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ entityID="https://demo.egiz.gv.at/demoportal_demologin/"
+ validUntil="2059-07-27T11:23:29.736Z">
+ <ds:Signature>
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod
+ Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+ <ds:SignatureMethod
+ Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
+ <ds:Reference
+ URI="#_c0303e3081ac29bb8329cade76279069">
+ <ds:Transforms>
+ <ds:Transform
+ Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ <ds:Transform
+ Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+ </ds:Transforms>
+ <ds:DigestMethod
+ Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
+ <ds:DigestValue>IjxuoZphYVmZdZ5HfoVDr35r2b1V840+SMeC89IO/SQ=
+ </ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>JILQKKPvsK7onsMweJauAcGEniFGJ5bXEOvfYhxAYCB+dXL6pH87USD1v9UqycllBDqQE/Rp2tPtqo11CjdcKs0KkceQCZjzmDlVPqMZrgh0FerTSysF0fcPKoKeAtqqk+WSu7Xk9lU+PCxGArGA+vBLTRRbAOuZpE7ORrS7AF2m5uaO1YOKfO0GN+LoxTiygI2aeqKsKMlPkboh4ZuEjv1ht9xUHeQtAf/MHtaXZDvaRQPXALf0oCRnDWpiiqvKdARJq5NXrrbrdow/M1FpoddtE0Mu65AsorIdXoPSXJnLhw/zDfHv82PQo0pW7ujc0yJY+5VzfURMZOyKmrfCmg==
+ </ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+ EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+ OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+ BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+ SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+ tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+ y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+ utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+ lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+ gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+ tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+ MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+ UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+ G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+ z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+ lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+ cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <md:SPSSODescriptor AuthnRequestsSigned="true"
+ WantAssertionsSigned="true"
+ protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor use="signing">
+ <ds:KeyInfo>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4
+ pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T
+ iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq
+ +TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU
+ cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ==
+ </ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ <ds:KeyValue>
+ <ds:RSAKeyValue>
+ <ds:Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
+ jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
+ 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
+ </ds:Modulus>
+ <ds:Exponent>AQAB</ds:Exponent>
+ </ds:RSAKeyValue>
+ </ds:KeyValue>
+ <!-- ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+ EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+ OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+ BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+ SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+ tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+ y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+ utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+ lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+ gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+ tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+ MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+ UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+ G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+ z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+ lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+ cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=
+ </ds:X509Certificate>
+ </ds:X509Data-->
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw
+ EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD
+ ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx
+ OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL
+ BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG
+ SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm
+ tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu
+ y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7
+ utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq
+ lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj
+ gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP
+ tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN
+ MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W
+ ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi
+ UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l
+ G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5
+ z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz
+ lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/
+ cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:SingleLogoutService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" />
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+ </md:NameIDFormat>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+ </md:NameIDFormat>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
+ </md:NameIDFormat>
+ <md:AssertionConsumerService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/post"
+ index="0" isDefault="true" />
+ <md:AssertionConsumerService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect"
+ index="1" />
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ
+ </md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government
+ Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at
+ </md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html
new file mode 100644
index 00000000..a0d31907
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html
@@ -0,0 +1,3 @@
+#if($RelayState)RelayState=${RelayState}"}#end
+#if($SAMLRequest)SAMLRequest=${SAMLRequest}"}#end
+#if($SAMLResponse)SAMLResponse=${SAMLResponse}"}#end \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml
new file mode 100644
index 00000000..59bb2e43
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" >
+
+ <context:annotation-config />
+
+ <bean id="dummyCredentialProvider"
+ class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider"
+ lazy-init="true"/>
+
+ <bean id="eaafKeyStoreFactory"
+ class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" />
+
+</beans>
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml
new file mode 100644
index 00000000..0c421356
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <!-- import resource="classpath:/spring/eaaf_utils.beans.xml" /-->
+
+ <bean id="dummyVelocityGuiBuilder"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" />
+
+ <bean id="dummyGuiBuilderConfigFactory"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" />
+
+</beans> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml
new file mode 100644
index 00000000..c1660a70
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="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
new file mode 100644
index 00000000..5319236b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <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" />
+
+</beans> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml
new file mode 100644
index 00000000..e7cc42ed
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <import resource="test_eaaf_core.beans.xml"/>
+ <import resource="classpath:/eaaf_pvp.beans.xml"/>
+
+ <bean id="dummyCredentialProvider"
+ class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" />
+
+ <bean id="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 69028266..ffda330d 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml
+++ b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml
@@ -5,10 +5,10 @@
<parent>
<groupId>at.gv.egiz.eaaf</groupId>
<artifactId>eaaf_modules</artifactId>
- <version>1.0.13.2</version>
+ <version>1.1.0</version>
</parent>
<artifactId>eaaf_module_pvp2_idp</artifactId>
- <name>eaaf_module_pvp2_core</name>
+ <name>eaaf_module_pvp2_idp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -32,6 +32,29 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_core_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>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_core</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
</dependencies>
<build>
@@ -49,21 +72,20 @@
</plugin>
<!-- enable co-existence of testng and junit -->
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>${surefire.version}</version>
- <configuration>
- <threadCount>1</threadCount>
- <argLine>--add-modules java.xml.bind</argLine>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>org.apache.maven.surefire</groupId>
- <artifactId>surefire-junit47</artifactId>
- <version>${surefire.version}</version>
- </dependency>
- </dependencies>
- </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
</plugins>
</build>
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java
deleted file mode 100644
index d50c5ee4..00000000
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.idp;
-
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-
-import at.gv.egiz.components.spring.api.SpringResourceProvider;
-
-public class PVP2SProfileIDPSpringResourceProvider implements SpringResourceProvider {
-
- @Override
- public String getName() {
- return "EAAF PVP2 S-Profile IDP SpringResourceProvider";
- }
-
- @Override
- public String[] getPackagesToScan() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Resource[] getResourcesToLoad() {
- ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml", PVP2SProfileIDPSpringResourceProvider.class);
-
- return new Resource[] {sl20AuthConfig};
- }
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java
new file mode 100644
index 00000000..7e572d70
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.idp;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+public class Pvp2SProfileIdpSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "EAAF PVP2 S-Profile IDP SpringResourceProvider";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml",
+ Pvp2SProfileIdpSpringResourceProvider.class);
+
+ return new Resource[] { sl20AuthConfig };
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java
index 90662f48..fd04e38f 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java
@@ -1,45 +1,39 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.api.builder;
import at.gv.egiz.eaaf.core.api.idp.IAuthData;
-import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
+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.exception.Pvp2Exception;
public interface ISubjectNameIdGenerator {
- /**
- * Generates a SAML2 subjectNameId from authentication data
- *
- * @param authData Authentication data for the current pending request
- * @param spConfig Service provider configuration
- * @return Pair of subjectNameId and NameIdFormat
- * @throws PVP2Exception
- */
- public Pair<String, String> generateSubjectNameId(IAuthData authData, ISPConfiguration spConfig) throws PVP2Exception;
+ /**
+ * Generates a SAML2 subjectNameId from authentication data.
+ *
+ * @param authData Authentication data for the current pending request
+ * @param spConfig Service provider configuration
+ * @return Pair of subjectNameId and NameIdFormat
+ * @throws Pvp2Exception In case of an error
+ */
+ Pair<String, String> generateSubjectNameId(IAuthData authData, ISpConfiguration spConfig)
+ throws Pvp2Exception;
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java
index 42424726..a7e05664 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java
@@ -1,54 +1,46 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-import org.opensaml.saml2.core.StatusCode;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+public class InvalidAssertionConsumerServiceException extends Pvp2Exception {
-public class InvalidAssertionConsumerServiceException extends PVP2Exception {
+ private static final long serialVersionUID = 7861790149343943091L;
- public InvalidAssertionConsumerServiceException(int idx) {
- super("pvp2.28", new Object[]{idx});
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
+ public InvalidAssertionConsumerServiceException(final int idx) {
+ super("pvp2.28", new Object[] { idx });
+ this.statusCodeValue = StatusCode.REQUESTER;
+ }
- /**
- *
- */
- public InvalidAssertionConsumerServiceException(String wrongURL) {
- super("pvp2.23", new Object[]{wrongURL});
- this.statusCodeValue = StatusCode.REQUESTER_URI;
-
- }
+ /**
+ * Invalid assertion consumer-service URL.
+ *
+ * @param wrongUrl invalid URL
+ */
+ public InvalidAssertionConsumerServiceException(final String wrongUrl) {
+ super("pvp2.23", new Object[] { wrongUrl });
+ this.statusCodeValue = StatusCode.REQUESTER;
- /**
- *
- */
- private static final long serialVersionUID = 7861790149343943091L;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java
index 55c94df1..89179ff6 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java
@@ -1,42 +1,35 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-import org.opensaml.saml2.core.StatusCode;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import org.opensaml.saml.saml2.core.StatusCode;
-public class InvalidAssertionEncryptionException extends PVP2Exception {
+public class InvalidAssertionEncryptionException extends Pvp2Exception {
- private static final long serialVersionUID = 6513388841485355549L;
+ private static final long serialVersionUID = 6513388841485355549L;
- public InvalidAssertionEncryptionException() {
- super("pvp2.16", new Object[]{});
- this.statusCodeValue = StatusCode.RESPONDER_URI;
- }
+ public InvalidAssertionEncryptionException() {
+ super("pvp2.16", new Object[] {});
+ this.statusCodeValue = StatusCode.RESPONDER;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java
index 6109c78d..cf4ac8d1 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java
@@ -1,45 +1,35 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-import org.opensaml.saml2.core.StatusCode;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import org.opensaml.saml.saml2.core.StatusCode;
-public class RequestDeniedException extends PVP2Exception {
+public class RequestDeniedException extends Pvp2Exception {
- public RequestDeniedException() {
- super("pvp2.14", null);
- this.statusCodeValue = StatusCode.REQUEST_DENIED_URI;
- }
+ private static final long serialVersionUID = 4415896615794730553L;
- /**
- *
- */
- private static final long serialVersionUID = 4415896615794730553L;
+ public RequestDeniedException() {
+ super("pvp2.14", null);
+ this.statusCodeValue = StatusCode.REQUEST_DENIED;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java
index 7f565c00..e6cdf8f1 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java
@@ -1,50 +1,40 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-import org.opensaml.saml2.core.StatusCode;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+public class ResponderErrorException extends Pvp2Exception {
-public class ResponderErrorException extends PVP2Exception {
+ private static final long serialVersionUID = -425416760138285446L;
- /**
- *
- */
- private static final long serialVersionUID = -425416760138285446L;
+ public ResponderErrorException(final String messageId, final Object[] parameters,
+ final Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ this.statusCodeValue = StatusCode.RESPONDER;
+ }
- public ResponderErrorException(String messageId, Object[] parameters,
- Throwable wrapped) {
- super(messageId, parameters, wrapped);
- this.statusCodeValue = StatusCode.RESPONDER_URI;
- }
-
- public ResponderErrorException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- this.statusCodeValue = StatusCode.RESPONDER_URI;
- }
+ public ResponderErrorException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ this.statusCodeValue = StatusCode.RESPONDER;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java
deleted file mode 100644
index a0fad363..00000000
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
-
-public class SAMLRequestNotSignedException extends PVP2Exception {
-
- public SAMLRequestNotSignedException() {
- super("pvp2.07", null);
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
-
- public SAMLRequestNotSignedException(Throwable e) {
- super("pvp2.07", null, e);
- this.statusCodeValue = StatusCode.REQUESTER_URI;
- }
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java
deleted file mode 100644
index e59ebe0a..00000000
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-
-import org.opensaml.saml2.core.StatusCode;
-
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
-
-
-public class SAMLRequestNotSupported extends PVP2Exception {
-
- public SAMLRequestNotSupported() {
- super("pvp2.09", null);
- this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED_URI;
- }
-
- /**
- *
- */
- private static final long serialVersionUID = 1244883178458802767L;
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java
new file mode 100644
index 00000000..add2103b
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
+
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public class SamlRequestNotSignedException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public SamlRequestNotSignedException() {
+ super("pvp2.07", null);
+ this.statusCodeValue = StatusCode.REQUESTER;
+ }
+
+ public SamlRequestNotSignedException(final Throwable e) {
+ super("pvp2.07", null, e);
+ this.statusCodeValue = StatusCode.REQUESTER;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java
new file mode 100644
index 00000000..d672f457
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
+
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
+
+public class SamlRequestNotSupported extends Pvp2Exception {
+
+ private static final long serialVersionUID = 1244883178458802767L;
+
+ public SamlRequestNotSupported() {
+ super("pvp2.09", null);
+ this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED;
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java
index 0dfda55f..3a56b414 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java
@@ -1,43 +1,34 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.exception;
-import org.opensaml.saml2.core.StatusCode;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+
+import org.opensaml.saml.saml2.core.StatusCode;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+public class UnprovideableAttributeException extends Pvp2Exception {
-public class UnprovideableAttributeException extends PVP2Exception {
- /**
- *
- */
- private static final long serialVersionUID = 3972197758163647157L;
+ private static final long serialVersionUID = 3972197758163647157L;
- public UnprovideableAttributeException(String attributeName) {
- super("pvp2.10", new Object[] {attributeName});
- this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE_URI;
- }
+ public UnprovideableAttributeException(final String attributeName) {
+ super("pvp2.10", new Object[] { attributeName });
+ this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE;
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java
new file mode 100644
index 00000000..597d3c22
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java
@@ -0,0 +1,549 @@
+/*******************************************************************************
+ * Copyright 2017 Graz University of Technology
+ * EAAF-Core Components has been developed in a cooperation between EGIZ,
+ * A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *******************************************************************************/
+/*******************************************************************************
+ *******************************************************************************/
+/*******************************************************************************
+ *******************************************************************************/
+package at.gv.egiz.eaaf.modules.pvp2.idp.impl;
+
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.saml2.core.AuthnRequest;
+import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.NameID;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.Status;
+import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.StatusMessage;
+import org.opensaml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.ws.security.SecurityPolicyException;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.signature.SignableXMLObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.gv.egiz.components.eventlog.api.EventConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
+import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
+import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
+import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;
+import at.gv.egiz.eaaf.core.exceptions.EAAFException;
+import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException;
+import at.gv.egiz.eaaf.core.exceptions.NoPassivAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.SLOException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
+import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor;
+import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPVPRequestException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.NameIDFormatNotSupportedException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionConsumerServiceException;
+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.binding.SoapBinding;
+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.utils.AbstractCredentialProvider;
+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.impl.validation.TrustEngineFactory;
+import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SAMLVerificationEngine;
+
+public abstract class AbstractPVP2XProtocol extends AbstractController implements IModulInfo {
+ private static final Logger log = LoggerFactory.getLogger(AbstractPVP2XProtocol.class);
+
+ @Autowired(required=true) protected IPVP2BasicConfiguration pvpBasicConfiguration;
+ @Autowired(required=true) protected IPVPMetadataProvider metadataProvider;
+ @Autowired(required=true) protected SAMLVerificationEngine samlVerificationEngine;
+ @Autowired(required=false) protected List<IAuthnRequestPostProcessor> authRequestPostProcessors;
+
+ private AbstractCredentialProvider pvpIDPCredentials;
+
+
+
+ /**
+ * Sets a specific credential provider for PVP S-Profile IDP component.
+ * @param pvpIDPCredentials credential provider
+ */
+ public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) {
+ this.pvpIDPCredentials = pvpIDPCredentials;
+
+ }
+
+ public boolean generateErrorMessage(Throwable e,
+ HttpServletRequest request, HttpServletResponse response,
+ IRequest protocolRequest) throws Throwable {
+
+ if(protocolRequest == null) {
+ throw e;
+ }
+
+ if(!(protocolRequest instanceof PVPSProfilePendingRequest) ) {
+ throw e;
+ }
+ PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest)protocolRequest;
+
+ Response samlResponse =
+ SAML2Utils.createSAMLObject(Response.class);
+ Status status = SAML2Utils.createSAMLObject(Status.class);
+ StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
+ StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class);
+
+ String moaError = null;
+
+ if(e instanceof NoPassivAuthenticationException) {
+ statusCode.setValue(StatusCode.NO_PASSIVE_URI);
+ statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
+
+ } else if (e instanceof NameIDFormatNotSupportedException) {
+ statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI);
+ statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
+
+ } else if (e instanceof SLOException) {
+ //SLOExecpetions only occurs if session information is lost
+ return false;
+
+ } else if(e instanceof PVP2Exception) {
+ PVP2Exception ex = (PVP2Exception) e;
+ statusCode.setValue(ex.getStatusCodeValue());
+ String statusMessageValue = ex.getStatusMessageValue();
+ if(statusMessageValue != null) {
+ statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue));
+ }
+ moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId());
+
+ } else {
+ statusCode.setValue(StatusCode.RESPONDER_URI);
+ statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));
+ moaError = statusMessager.getResponseErrorCode(e);
+ }
+
+
+ if (StringUtils.isNotEmpty(moaError)) {
+ StatusCode moaStatusCode = SAML2Utils.createSAMLObject(StatusCode.class);
+ moaStatusCode.setValue(moaError);
+ statusCode.setStatusCode(moaStatusCode);
+ }
+
+ status.setStatusCode(statusCode);
+ if(statusMessage.getMessage() != null) {
+ status.setStatusMessage(statusMessage);
+ }
+ samlResponse.setStatus(status);
+ String remoteSessionID = SAML2Utils.getSecureIdentifier();
+ samlResponse.setID(remoteSessionID);
+
+ samlResponse.setIssueInstant(new DateTime());
+ Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class);
+ nissuer.setValue(pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL()));
+ nissuer.setFormat(NameID.ENTITY);
+ samlResponse.setIssuer(nissuer);
+
+ IEncoder encoder = null;
+
+ if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
+ encoder = applicationContext.getBean("PVPRedirectBinding", RedirectBinding.class);
+
+ } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
+ encoder = applicationContext.getBean("PVPPOSTBinding", PostBinding.class);
+
+ } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) {
+ encoder = applicationContext.getBean("PVPSOAPBinding", SoapBinding.class);
+ }
+
+ if(encoder == null) {
+ // default to redirect binding
+ encoder = new RedirectBinding();
+ }
+
+ String relayState = null;
+ if (pvpRequest.getRequest() != null)
+ relayState = pvpRequest.getRequest().getRelayState();
+
+ X509Credential signCred = pvpIDPCredentials.getIDPAssertionSigningCredential();
+
+ encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(),
+ relayState, signCred, protocolRequest);
+ return true;
+ }
+
+ public boolean validate(HttpServletRequest request,
+ HttpServletResponse response, IRequest pending) {
+
+ return true;
+ }
+
+ protected void pvpMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {
+ //create pendingRequest object
+ PVPSProfilePendingRequest pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
+ pendingReq.initialize(req, authConfig);
+ pendingReq.setModule(getName());
+
+ revisionsLogger.logEvent(
+ pendingReq.getUniqueSessionIdentifier(),
+ pendingReq.getUniqueTransactionIdentifier(),
+ EventConstants.TRANSACTION_IP,
+ req.getRemoteAddr());
+
+ MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class);
+ metadataAction.processRequest(pendingReq,
+ req, resp, null);
+
+ }
+
+ protected void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {
+ PVPSProfilePendingRequest pendingReq = null;
+
+ try {
+ //create pendingRequest object
+ pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
+ pendingReq.initialize(req, authConfig);
+ pendingReq.setModule(getName());
+
+ revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier());
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(
+ pendingReq.getUniqueSessionIdentifier(),
+ pendingReq.getUniqueTransactionIdentifier(),
+ EventConstants.TRANSACTION_IP,
+ req.getRemoteAddr());
+
+ //get POST-Binding decoder implementation
+ InboundMessage msg = (InboundMessage) new PostBinding().decode(
+ req, resp, metadataProvider, false,
+ new EAAFURICompare(pvpBasicConfiguration.getIDPSSOPostService(pendingReq.getAuthURL())));
+ pendingReq.setRequest(msg);
+
+ //preProcess Message
+ preProcess(req, resp, pendingReq);
+
+ } catch (SecurityPolicyException e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.warn("Receive INVALID protocol request: " + samlRequest, e);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
+
+ } catch (SecurityException e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.warn("Receive INVALID protocol request: " + samlRequest, e);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
+
+ } catch (EAAFException e) {
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw e;
+
+ } catch (Throwable e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.warn("Receive INVALID protocol request: " + samlRequest, e);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e);
+ }
+ }
+
+ protected void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException {
+ PVPSProfilePendingRequest pendingReq = null;
+ try {
+ //create pendingRequest object
+ pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class);
+ pendingReq.initialize(req, authConfig);
+ pendingReq.setModule(getName());
+
+ revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier());
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(
+ pendingReq.getUniqueSessionIdentifier(),
+ pendingReq.getUniqueTransactionIdentifier(),
+ EventConstants.TRANSACTION_IP,
+ req.getRemoteAddr());
+
+ //get POST-Binding decoder implementation
+ InboundMessage msg = (InboundMessage) new RedirectBinding().decode(
+ req, resp, metadataProvider, false,
+ new EAAFURICompare(pvpBasicConfiguration.getIDPSSORedirectService(pendingReq.getAuthURL())));
+ pendingReq.setRequest(msg);
+
+ //preProcess Message
+ preProcess(req, resp, pendingReq);
+
+ } catch (SecurityPolicyException e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.warn("Receive INVALID protocol request: " + samlRequest, e);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});
+
+ } catch (SecurityException e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.warn("Receive INVALID protocol request: " + samlRequest, e);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()});
+
+ } catch (EAAFException e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.info("Receive INVALID protocol request: " + samlRequest);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw e;
+
+ } catch (Throwable e) {
+ String samlRequest = req.getParameter("SAMLRequest");
+ log.warn("Receive INVALID protocol request: " + samlRequest, e);
+
+ //write revision log entries
+ if (pendingReq != null)
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier());
+
+ throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e);
+ }
+ }
+
+
+
+ /**
+ *
+ *
+ * @param request
+ * @param response
+ * @param msg
+ * @return true if preprocess can handle this request type, otherwise false
+ * @throws Throwable
+ */
+ abstract protected boolean childPreProcess(HttpServletRequest request,
+ HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable;
+
+ protected void preProcess(HttpServletRequest request,
+ HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable {
+
+ InboundMessage msg = pendingReq.getRequest();
+
+ if (StringUtils.isEmpty(msg.getEntityID())) {
+ throw new InvalidProtocolRequestException("pvp2.20", new Object[] {});
+
+ }
+
+ if(!msg.isVerified()) {
+ samlVerificationEngine.verify(msg,
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+ msg.setVerified(true);
+
+ }
+
+ revisionsLogger.logEvent(pendingReq, IRevisionLogger.AUTHPROTOCOL_TYPE, getAuthProtocolIdentifier());
+
+ if (msg instanceof PVPSProfileRequest &&
+ ((PVPSProfileRequest)msg).getSamlRequest() instanceof AuthnRequest)
+ preProcessAuthRequest(request, response, pendingReq);
+
+ else if (childPreProcess(request, response, pendingReq))
+ log.debug("Find protocol handler in child implementation");
+
+ else {
+ log.error("Receive unsupported PVP21 message of type: " + ((PVPSProfileRequest)msg).getSamlRequest().getClass().getName());
+ throw new InvalidPVPRequestException("pvp2.09",
+ new Object[] {((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()});
+ }
+
+
+
+ //switch to session authentication
+ protAuthService.performAuthentication(request, response, pendingReq);
+ }
+
+
+ /**
+ * PreProcess Authn request
+ * @param request
+ * @param response
+ * @param pendingReq
+ * @throws Throwable
+ */
+ private void preProcessAuthRequest(HttpServletRequest request,
+ HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable {
+
+ PVPSProfileRequest moaRequest = ((PVPSProfileRequest)pendingReq.getRequest());
+ SignableXMLObject samlReq = moaRequest.getSamlRequest();
+
+ if(!(samlReq instanceof AuthnRequest)) {
+ throw new InvalidPVPRequestException("Unsupported request", new Object[] {});
+ }
+
+ EntityDescriptor metadata = moaRequest.getEntityMetadata(metadataProvider);
+ if(metadata == null) {
+ throw new NoMetadataInformationException();
+ }
+ SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+
+ AuthnRequest authnRequest = (AuthnRequest)samlReq;
+
+ if (authnRequest.getIssueInstant() == null) {
+ log.warn("Unsupported request: No IssueInstant Attribute found.");
+ throw new AuthnRequestValidatorException("pvp2.22",
+ new Object[] {"Unsupported request: No IssueInstant Attribute found"},
+ pendingReq);
+
+ }
+
+ if (authnRequest.getIssueInstant().minusMinutes(EAAFConstants.ALLOWED_TIME_JITTER).isAfterNow()) {
+ log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore.");
+ throw new AuthnRequestValidatorException("pvp2.22",
+ new Object[] {"Unsupported request: No IssueInstant DateTime is not valid anymore."},
+ pendingReq);
+
+ }
+
+ //parse AssertionConsumerService
+ AssertionConsumerService consumerService = null;
+ if (StringUtils.isNotEmpty(authnRequest.getAssertionConsumerServiceURL()) &&
+ StringUtils.isNotEmpty(authnRequest.getProtocolBinding())) {
+ //use AssertionConsumerServiceURL from request
+
+ //check requested AssertionConsumingService URL against metadata
+ List<AssertionConsumerService> metadataAssertionServiceList = spSSODescriptor.getAssertionConsumerServices();
+ for (AssertionConsumerService service : metadataAssertionServiceList) {
+ if (authnRequest.getProtocolBinding().equals(service.getBinding())
+ && authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) {
+ consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class);
+ consumerService.setBinding(authnRequest.getProtocolBinding());
+ consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL());
+ log.debug("Requested AssertionConsumerServiceURL is valid.");
+ }
+ }
+
+ if (consumerService == null) {
+ throw new InvalidAssertionConsumerServiceException(authnRequest.getAssertionConsumerServiceURL());
+
+ }
+
+
+ } else {
+ //use AssertionConsumerServiceIndex and select consumerService from metadata
+ Integer aIdx = authnRequest.getAssertionConsumerServiceIndex();
+ int assertionidx = 0;
+
+ if(aIdx != null) {
+ assertionidx = aIdx.intValue();
+
+ } else {
+ assertionidx = SAML2Utils.getDefaultAssertionConsumerServiceIndex(spSSODescriptor);
+
+ }
+ consumerService = spSSODescriptor.getAssertionConsumerServices().get(assertionidx);
+
+ if (consumerService == null) {
+ throw new InvalidAssertionConsumerServiceException(aIdx);
+
+ }
+ }
+
+
+ //validate AuthnRequest
+ AuthnRequest authReq = (AuthnRequest) samlReq;
+ String oaURL = moaRequest.getEntityMetadata(metadataProvider).getEntityID();
+ log.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding());
+
+ pendingReq.setSPEntityId(StringEscapeUtils.escapeHtml(oaURL));
+ pendingReq.setOnlineApplicationConfiguration(authConfig.getServiceProviderConfiguration(pendingReq.getSPEntityId()));
+ pendingReq.setBinding(consumerService.getBinding());
+ pendingReq.setRequest(moaRequest);
+ pendingReq.setConsumerURL(consumerService.getLocation());
+
+ //parse AuthRequest
+ pendingReq.setPassiv(authReq.isPassive());
+ pendingReq.setForce(authReq.isForceAuthn());
+
+ //AuthnRequest needs authentication
+ pendingReq.setNeedAuthentication(true);
+
+ //set protocol action, which should be executed after authentication
+ pendingReq.setAction(AuthenticationAction.class.getName());
+
+ // do post-processing if required
+ log.trace("Starting extended AuthnRequest validation and processing ... ");
+ if (authRequestPostProcessors != null) {
+ for (final IAuthnRequestPostProcessor processor : authRequestPostProcessors) {
+ log.trace("Post-process AuthnRequest with module: {}", processor.getClass().getSimpleName());
+ processor.process(request, pendingReq, authReq, spSSODescriptor);
+
+ }
+ }
+
+ log.debug("Extended AuthnRequest validation and processing finished");
+
+ //write revisionslog entry
+ revisionsLogger.logEvent(pendingReq, PVPEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST, authReq.getID());
+
+ }
+
+ @PostConstruct
+ private void verifyInitialization() {
+ if (pvpIDPCredentials == null) {
+ log.error("No SAML2 credentialProvider injected!");
+ throw new RuntimeException("No SAML2 credentialProvider injected!");
+
+ }
+ }
+
+}
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 cbbed659..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
@@ -1,29 +1,22 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.impl;
import javax.annotation.PostConstruct;
@@ -31,14 +24,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.core.Assertion;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.xml.security.SecurityException;
+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;
@@ -49,137 +40,139 @@ 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;
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
-import at.gv.egiz.eaaf.core.exceptions.EAAFException;
-import at.gv.egiz.eaaf.core.impl.data.SLOInformationImpl;
-import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.data.SloInformationImpl;
+import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder;
-import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider;
import at.gv.egiz.eaaf.modules.pvp2.exception.BindingNotSupportedException;
import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException;
import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.PVP2AssertionBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.Pvp2AssertionBuilder;
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.message.PVPSProfileRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
@Service("PVPAuthenticationRequestAction")
public class AuthenticationAction implements IAction {
- private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class);
-
- private static final String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = "protocols.pvp2.assertion.encryption.active";
-
- @Autowired(required=true) private IPVPMetadataProvider metadataProvider;
- @Autowired(required=true) ApplicationContext springContext;
- @Autowired(required=true) IConfiguration authConfig;
- @Autowired(required=true) PVP2AssertionBuilder assertionBuilder;
- @Autowired(required=true) IPVP2BasicConfiguration pvpBasicConfiguration;
- @Autowired(required=true) IRevisionLogger revisionsLogger;
-
- private AbstractCredentialProvider pvpIDPCredentials;
-
- /**
- * Sets a specific credential provider for PVP S-Profile IDP component.
- * @param pvpIDPCredentials credential provider
- */
- public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) {
- this.pvpIDPCredentials = pvpIDPCredentials;
-
- }
-
- @Override
- public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq,
- HttpServletResponse httpResp, IAuthData authData) throws ResponderErrorException {
- final PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest) req;
- try {
- //get basic information
- final PVPSProfileRequest moaRequest = (PVPSProfileRequest) pvpRequest.getRequest();
- final AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest();
- final EntityDescriptor peerEntity = moaRequest.getEntityMetadata(metadataProvider);
-
- final AssertionConsumerService consumerService =
- SAML2Utils.createSAMLObject(AssertionConsumerService.class);
- consumerService.setBinding(pvpRequest.getBinding());
- consumerService.setLocation(pvpRequest.getConsumerURL());
-
- final DateTime date = new DateTime();
- final SLOInformationImpl sloInformation = new SLOInformationImpl();
- final String issuerEntityID = pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL());
-
- //build Assertion
- final Assertion assertion = assertionBuilder.buildAssertion(issuerEntityID, pvpRequest, authnRequest, authData,
- peerEntity, date, consumerService, sloInformation);
-
- final Response authResponse = AuthResponseBuilder.buildResponse(
- metadataProvider, issuerEntityID, authnRequest,
- date, assertion, authConfig.getBasicConfigurationBoolean(
- CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true));
-
- IEncoder binding = null;
-
- if (consumerService.getBinding().equals(
- SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
- binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class);
-
- } else if (consumerService.getBinding().equals(
- SAMLConstants.SAML2_POST_BINDING_URI)) {
- binding = springContext.getBean("PVPPOSTBinding", PostBinding.class);
-
- }
-
- if (binding == null) {
- throw new BindingNotSupportedException(consumerService.getBinding());
- }
-
- binding.encodeRespone(httpReq, httpResp, authResponse,
- consumerService.getLocation(), moaRequest.getRelayState(),
- pvpIDPCredentials.getIDPAssertionSigningCredential(), req);
-
- revisionsLogger.logEvent(req, 3105, authResponse.getID());
-
- //set protocol type
- sloInformation.setProtocolType(req.requestedModule());
- sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier());
- return sloInformation;
-
- } catch (MessageEncodingException | SecurityException e) {
- log.warn("Message Encoding exception", e);
- throw new ResponderErrorException("pvp2.01", null, e);
-
- } catch (final EAAFException e) {
- log.info("Response generation error: Msg: ", e.getMessage());
- throw new ResponderErrorException(e.getErrorId(), e.getParams(), e);
-
- } catch (final Exception e) {
- log.warn("Response generation error", e);
- throw new ResponderErrorException("pvp2.01", null, e);
-
- }
-
- }
-
- @Override
- public boolean needAuthentication(IRequest req, HttpServletRequest httpReq,
- HttpServletResponse httpResp) {
- return true;
- }
-
- @Override
- public String getDefaultActionName() {
- return "PVPAuthenticationRequestAction";
-
- }
-
- @PostConstruct
- private void verifyInitialization() {
- if (pvpIDPCredentials == null) {
- log.error("No SAML2 credentialProvider injected!");
- throw new RuntimeException("No SAML2 credentialProvider injected!");
-
- }
- }
+ private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class);
+
+ @Autowired(required = true)
+ private IPvp2MetadataProvider metadataProvider;
+ @Autowired(required = true)
+ ApplicationContext springContext;
+ @Autowired(required = true)
+ IConfiguration authConfig;
+ @Autowired(required = true)
+ Pvp2AssertionBuilder assertionBuilder;
+ @Autowired(required = true)
+ IPvp2BasicConfiguration pvpBasicConfiguration;
+ @Autowired(required = true)
+ IRevisionLogger revisionsLogger;
+
+ private IPvp2CredentialProvider pvpIdpCredentials;
+
+ /**
+ * Sets a specific credential provider for PVP S-Profile IDP component.
+ *
+ * @param pvpIdpCredentials credential provider
+ */
+ public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) {
+ this.pvpIdpCredentials = pvpIdpCredentials;
+
+ }
+
+ @Override
+ public SloInformationInterface processRequest(final IRequest req,
+ final HttpServletRequest httpReq, final HttpServletResponse httpResp,
+ final IAuthData authData) throws ResponderErrorException {
+ final PvpSProfilePendingRequest pvpRequest = (PvpSProfilePendingRequest) req;
+ try {
+ // get basic information
+ final PvpSProfileRequest moaRequest = (PvpSProfileRequest) pvpRequest.getRequest();
+ final AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest();
+ final EntityDescriptor peerEntity = moaRequest.getEntityMetadata(metadataProvider);
+
+ final AssertionConsumerService consumerService =
+ Saml2Utils.createSamlObject(AssertionConsumerService.class);
+ consumerService.setBinding(pvpRequest.getBinding());
+ consumerService.setLocation(pvpRequest.getConsumerUrl());
+
+ final DateTime date = new DateTime();
+ final SloInformationImpl sloInformation = new SloInformationImpl();
+ final String issuerEntityID = pvpBasicConfiguration.getIdpEntityId(pvpRequest.getAuthUrl());
+
+ // build Assertion
+ final Assertion assertion = assertionBuilder.buildAssertion(issuerEntityID, pvpRequest,
+ authnRequest, authData, peerEntity, date, consumerService, sloInformation);
+
+ final Response authResponse = AuthResponseBuilder.buildResponse(metadataProvider,
+ issuerEntityID, authnRequest, date, assertion,
+ authConfig);
+
+ IEncoder binding = null;
+
+ if (consumerService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
+ binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class);
+
+ } else if (consumerService.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
+ binding = springContext.getBean("PvpPostBinding", PostBinding.class);
+
+ }
+
+ if (binding == null) {
+ throw new BindingNotSupportedException(consumerService.getBinding());
+ }
+
+ binding.encodeResponse(httpReq, httpResp, authResponse, consumerService.getLocation(),
+ moaRequest.getRelayState(), pvpIdpCredentials.getMessageSigningCredential(), req);
+
+ revisionsLogger.logEvent(req, 3105, authResponse.getID());
+
+ // set protocol type
+ sloInformation.setProtocolType(req.requestedModule());
+ sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier());
+ return sloInformation;
+
+ } catch (final SecurityException e) {
+ log.warn("Message Encoding exception", e);
+ throw new ResponderErrorException("pvp2.01", null, e);
+
+ } catch (final EaafException e) {
+ log.info("Response generation error: Msg: ", e.getMessage());
+ throw new ResponderErrorException(e.getErrorId(), e.getParams(), e);
+
+ } catch (final Exception e) {
+ log.warn("Response generation error", e);
+ throw new ResponderErrorException("pvp2.01", null, e);
+
+ }
+
+ }
+
+ @Override
+ public boolean needAuthentication(final IRequest req, final HttpServletRequest httpReq,
+ final HttpServletResponse httpResp) {
+ return true;
+ }
+
+ @Override
+ public String getDefaultActionName() {
+ return "PVPAuthenticationRequestAction";
+
+ }
+
+ @PostConstruct
+ private void verifyInitialization() {
+ if (pvpIdpCredentials == null) {
+ log.error("No SAML2 credentialProvider injected!");
+ throw new RuntimeException("No SAML2 credentialProvider injected!");
+
+ }
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java
index 6b957522..0b344ba3 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java
@@ -1,123 +1,120 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.impl;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.IAction;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
+import at.gv.egiz.eaaf.modules.pvp2.PvpEventConstants;
+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.exception.Pvp2MetadataException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
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;
-import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface;
-import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
-import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants;
-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.exception.PVP2MetadataException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPMetadataBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider;
-
@Service("pvpMetadataService")
public class MetadataAction implements IAction {
- private static final Logger log = LoggerFactory.getLogger(MetadataAction.class);
-
- @Autowired private IRevisionLogger revisionsLogger;
- @Autowired private PVPMetadataBuilder metadatabuilder;
- @Autowired private IPVPMetadataConfigurationFactory configFactory;
-
- private AbstractCredentialProvider pvpIDPCredentials;
-
- /**
- * Sets a specific credential provider for PVP S-Profile IDP component.
- * @param pvpIDPCredentials credential provider
- */
- public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) {
- this.pvpIDPCredentials = pvpIDPCredentials;
-
- }
-
- public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq,
- HttpServletResponse httpResp, IAuthData authData) throws PVP2MetadataException {
- try {
- revisionsLogger.logEvent(req, PVPEventConstants.AUTHPROTOCOL_PVP_METADATA);
-
- //build metadata
- IPVPMetadataBuilderConfiguration metadataConfig =
- configFactory.generateMetadataBuilderConfiguration(
- req.getAuthURLWithOutSlash(),
- pvpIDPCredentials);
-
- ;
-
- String metadataXML = metadatabuilder.buildPVPMetadata(metadataConfig);
- log.debug("METADATA: " + metadataXML);
-
- byte[] content = metadataXML.getBytes("UTF-8");
- httpResp.setStatus(HttpServletResponse.SC_OK);
- httpResp.setContentLength(content.length);
- httpResp.setContentType(MediaType.APPLICATION_XML_VALUE);
- httpResp.getOutputStream().write(content);
- return null;
-
- } catch (Exception e) {
- log.error("Failed to generate metadata", e);
- throw new PVP2MetadataException("pvp2.27", null);
- }
- }
-
- public boolean needAuthentication(IRequest req, HttpServletRequest httpReq,
- HttpServletResponse httpResp) {
- return false;
- }
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName()
- */
- @Override
- public String getDefaultActionName() {
- return "IDP - PVP Metadata action";
- }
-
- @PostConstruct
- private void verifyInitialization() {
- if (pvpIDPCredentials == null) {
- log.error("No SAML2 credentialProvider injected!");
- throw new RuntimeException("No SAML2 credentialProvider injected!");
-
- }
- }
-
+ private static final Logger log = LoggerFactory.getLogger(MetadataAction.class);
+
+ @Autowired
+ private IRevisionLogger revisionsLogger;
+ @Autowired
+ private PvpMetadataBuilder metadatabuilder;
+ @Autowired
+ private IPvpMetadataConfigurationFactory configFactory;
+
+ private IPvp2CredentialProvider pvpIdpCredentials;
+
+ /**
+ * Sets a specific credential provider for PVP S-Profile IDP component.
+ *
+ * @param pvpIdpCredentials credential provider
+ */
+ public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) {
+ this.pvpIdpCredentials = pvpIdpCredentials;
+
+ }
+
+ @Override
+ public SloInformationInterface processRequest(final IRequest req,
+ final HttpServletRequest httpReq, final HttpServletResponse httpResp,
+ final IAuthData authData) throws Pvp2MetadataException {
+ try {
+ revisionsLogger.logEvent(req, PvpEventConstants.AUTHPROTOCOL_PVP_METADATA);
+
+ // build metadata
+ final IPvpMetadataBuilderConfiguration metadataConfig = configFactory
+ .generateMetadataBuilderConfiguration(req.getAuthUrlWithOutSlash(), pvpIdpCredentials);
+
+ final String metadataXml = metadatabuilder.buildPvpMetadata(metadataConfig);
+ log.trace("METADATA: " + metadataXml);
+
+ final byte[] content = metadataXml.getBytes("UTF-8");
+ httpResp.setStatus(HttpServletResponse.SC_OK);
+ httpResp.setContentLength(content.length);
+ httpResp.setContentType(MediaType.APPLICATION_XML_VALUE);
+ httpResp.getOutputStream().write(content);
+ return null;
+
+ } catch (final Exception e) {
+ log.error("Failed to generate metadata", e);
+ throw new Pvp2MetadataException("pvp2.27", null);
+ }
+ }
+
+ @Override
+ public boolean needAuthentication(final IRequest req, final HttpServletRequest httpReq,
+ final HttpServletResponse httpResp) {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName()
+ */
+ @Override
+ public String getDefaultActionName() {
+ return "IDP - PVP Metadata action";
+ }
+
+ @PostConstruct
+ private void verifyInitialization() {
+ if (pvpIdpCredentials == null) {
+ log.error("No SAML2 credentialProvider injected!");
+ throw new RuntimeException("No SAML2 credentialProvider injected!");
+
+ }
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java
deleted file mode 100644
index 7f086ff6..00000000
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.idp.impl;
-
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.context.annotation.Scope;
-import org.springframework.stereotype.Component;
-
-import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
-import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
-
-@Component("PVPSProfilePendingRequest")
-@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
-public class PVPSProfilePendingRequest extends RequestImpl {
- private static final long serialVersionUID = 4889919265919638188L;
-
- InboundMessage request;
- String binding;
- String consumerURL;
-
- public InboundMessage getRequest() {
- return request;
- }
-
- public void setRequest(InboundMessage request) {
- this.request = request;
- }
-
- public String getBinding() {
- return binding;
- }
-
- public void setBinding(String binding) {
- this.binding = binding;
- }
-
- public String getConsumerURL() {
- return consumerURL;
- }
-
- public void setConsumerURL(String consumerURL) {
- this.consumerURL = consumerURL;
-
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java
new file mode 100644
index 00000000..26e04881
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.idp.impl;
+
+import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Component("PVPSProfilePendingRequest")
+@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
+public class PvpSProfilePendingRequest extends RequestImpl {
+ private static final long serialVersionUID = 4889919265919638188L;
+
+ InboundMessage request;
+ String binding;
+ String consumerUrl;
+
+ public InboundMessage getRequest() {
+ return request;
+ }
+
+ public void setRequest(final InboundMessage request) {
+ this.request = request;
+ }
+
+ public String getBinding() {
+ return binding;
+ }
+
+ public void setBinding(final String binding) {
+ this.binding = binding;
+ }
+
+ public String getConsumerUrl() {
+ return consumerUrl;
+ }
+
+ public void setConsumerUrl(final String consumerUrl) {
+ this.consumerUrl = consumerUrl;
+
+ }
+}
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 07423c19..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
@@ -1,153 +1,215 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder;
import java.util.ArrayList;
import java.util.List;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException;
+import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
import org.joda.time.DateTime;
-import org.opensaml.Configuration;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.core.Assertion;
-import org.opensaml.saml2.core.EncryptedAssertion;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.NameID;
-import org.opensaml.saml2.core.RequestAbstractType;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.encryption.Encrypter;
-import org.opensaml.saml2.encryption.Encrypter.KeyPlacement;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.security.MetadataCredentialResolver;
-import org.opensaml.security.MetadataCriteria;
-import org.opensaml.xml.encryption.EncryptionException;
-import org.opensaml.xml.encryption.EncryptionParameters;
-import org.opensaml.xml.encryption.KeyEncryptionParameters;
-import org.opensaml.xml.security.CriteriaSet;
-import org.opensaml.xml.security.SecurityException;
-import org.opensaml.xml.security.credential.UsageType;
-import org.opensaml.xml.security.criteria.EntityIDCriteria;
-import org.opensaml.xml.security.criteria.UsageCriteria;
-import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
-import org.opensaml.xml.security.x509.X509Credential;
+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;
+import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.EncryptedAssertion;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.encryption.Encrypter;
+import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml.security.impl.MetadataCredentialResolver;
+import org.opensaml.security.credential.UsageType;
+import org.opensaml.security.criteria.UsageCriterion;
+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.KeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory;
+import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver;
+import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider;
+import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
/**
+ * Authentication response builder.
+ *
* @author tlenz
*
*/
public class AuthResponseBuilder {
- private static final Logger log = LoggerFactory.getLogger(AuthResponseBuilder.class);
-
- public static Response buildResponse(MetadataProvider metadataProvider, String issuerEntityID, RequestAbstractType req, DateTime date, Assertion assertion, boolean enableEncryption) throws InvalidAssertionEncryptionException {
- Response authResponse = SAML2Utils.createSAMLObject(Response.class);
-
- Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class);
-
- nissuer.setValue(issuerEntityID);
- nissuer.setFormat(NameID.ENTITY);
- authResponse.setIssuer(nissuer);
- authResponse.setInResponseTo(req.getID());
-
- //set responseID
- String remoteSessionID = SAML2Utils.getSecureIdentifier();
- authResponse.setID(remoteSessionID);
-
-
- //SAML2 response required IssueInstant
- authResponse.setIssueInstant(date);
-
- authResponse.setStatus(SAML2Utils.getSuccessStatus());
-
- //check, if metadata includes an encryption key
- MetadataCredentialResolver mdCredResolver =
- new MetadataCredentialResolver(metadataProvider);
-
- CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add( new EntityIDCriteria(req.getIssuer().getValue()) );
- criteriaSet.add( new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) );
- criteriaSet.add( new UsageCriteria(UsageType.ENCRYPTION) );
-
- X509Credential encryptionCredentials = null;
- try {
- encryptionCredentials = (X509Credential) mdCredResolver.resolveSingle(criteriaSet);
-
- } catch (SecurityException e2) {
- log.warn("Can not extract the Assertion Encryption-Key from metadata", e2);
- throw new InvalidAssertionEncryptionException();
-
- }
-
- if (encryptionCredentials != null && enableEncryption) {
- //encrypt SAML2 assertion
-
- try {
-
- EncryptionParameters dataEncParams = new EncryptionParameters();
- dataEncParams.setAlgorithm(PVPConstants.DEFAULT_SYM_ENCRYPTION_METHODE);
-
- List<KeyEncryptionParameters> keyEncParamList = new ArrayList<KeyEncryptionParameters>();
- KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters();
-
- keyEncParam.setEncryptionCredential(encryptionCredentials);
- keyEncParam.setAlgorithm(PVPConstants.DEFAULT_ASYM_ENCRYPTION_METHODE);
- KeyInfoGeneratorFactory kigf = Configuration.getGlobalSecurityConfiguration()
- .getKeyInfoGeneratorManager().getDefaultManager()
- .getFactory(encryptionCredentials);
- keyEncParam.setKeyInfoGenerator(kigf.newInstance());
- keyEncParamList.add(keyEncParam);
-
- Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList);
- //samlEncrypter.setKeyPlacement(KeyPlacement.INLINE);
- samlEncrypter.setKeyPlacement(KeyPlacement.PEER);
-
- EncryptedAssertion encryptAssertion = null;
-
- encryptAssertion = samlEncrypter.encrypt(assertion);
-
- authResponse.getEncryptedAssertions().add(encryptAssertion);
-
- } catch (EncryptionException e1) {
- log.warn("Can not encrypt the PVP2 assertion", e1);
- throw new InvalidAssertionEncryptionException();
-
- }
-
- } else {
- authResponse.getAssertions().add(assertion);
-
- }
-
- return authResponse;
- }
+ private static final Logger log = LoggerFactory.getLogger(AuthResponseBuilder.class);
+
+ /**
+ * Build PVP2 S-Profile authentication response.
+ *
+ * @param metadataProvider Service-Provider metadata
+ * @param issuerEntityID IDP entityId
+ * @param req current pending request
+ * @param date Timestamp
+ * @param assertion PVP2 S-Profil Assertion
+ * @param authConfig {@link IConfiguration}
+ * @return PVP2 S-Profile authentication response
+ * @throws InvalidAssertionEncryptionException In case of an error
+ */
+ public static Response buildResponse(final IPvp2MetadataProvider metadataProvider,
+ final String issuerEntityID, final RequestAbstractType req, final DateTime date,
+ final Assertion assertion, IConfiguration authConfig)
+ throws InvalidAssertionEncryptionException {
+ final Response authResponse = Saml2Utils.createSamlObject(Response.class);
+
+ final Issuer nissuer = Saml2Utils.createSamlObject(Issuer.class);
+
+ nissuer.setValue(issuerEntityID);
+ nissuer.setFormat(NameIDType.ENTITY);
+ authResponse.setIssuer(nissuer);
+ authResponse.setInResponseTo(req.getID());
+
+ // set responseID
+ final String remoteSessionID = Saml2Utils.getSecureIdentifier();
+ authResponse.setID(remoteSessionID);
+
+ // SAML2 response required IssueInstant
+ authResponse.setIssueInstant(date);
+
+ authResponse.setStatus(Saml2Utils.getSuccessStatus());
+
+ // check, if metadata includes an encryption key
+ final X509Credential encryptionCredentials = resolveEncryptionCredential(req, metadataProvider);
+
+ if (encryptionCredentials != null
+ && authConfig.getBasicConfigurationBoolean(
+ PvpConstants.CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)) {
+ authResponse.getEncryptedAssertions().add(
+ doEncryption(assertion, encryptionCredentials, authConfig));
+
+ } else {
+ authResponse.getAssertions().add(assertion);
+
+ }
+
+ return authResponse;
+ }
+
+ private static EncryptedAssertion doEncryption(Assertion assertion,
+ X509Credential encryptionCredentials, IConfiguration authConfig)
+ throws InvalidAssertionEncryptionException {
+ 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);
+
+ 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");
+
+ 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();
+
+ }
+
+ }
+
+ private static X509Credential resolveEncryptionCredential(RequestAbstractType req,
+ IPvp2MetadataProvider metadataProvider) throws InvalidAssertionEncryptionException {
+ try {
+ final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>();
+ keyInfoProvider.add(new DSAKeyValueProvider());
+ keyInfoProvider.add(new RSAKeyValueProvider());
+ keyInfoProvider.add(new InlineX509DataProvider());
+ final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver(
+ keyInfoProvider);
+
+ final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver(
+ metadataProvider);
+ roleDescriptorResolver.setRequireValidMetadata(true);
+ roleDescriptorResolver.initialize();
+
+ final MetadataCredentialResolver mdCredResolver = new MetadataCredentialResolver();
+ mdCredResolver.setRoleDescriptorResolver(roleDescriptorResolver);
+ mdCredResolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver);
+ mdCredResolver.initialize();
+
+ final CriteriaSet criteriaSet = new CriteriaSet();
+ criteriaSet.add(new EntityIdCriterion(req.getIssuer().getValue()));
+ criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS));
+ criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
+ criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION));
+
+ return (X509Credential) mdCredResolver.resolveSingle(criteriaSet);
+
+ } catch (final SecurityException | ComponentInitializationException | ResolverException e2) {
+ log.warn("Can not extract the Assertion Encryption-Key from metadata", e2);
+ throw new InvalidAssertionEncryptionException();
+
+ }
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java
deleted file mode 100644
index 2ccc2c9e..00000000
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder;
-
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.core.Assertion;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.core.AttributeQuery;
-import org.opensaml.saml2.core.AttributeStatement;
-import org.opensaml.saml2.core.Audience;
-import org.opensaml.saml2.core.AudienceRestriction;
-import org.opensaml.saml2.core.AuthnContext;
-import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.AuthnStatement;
-import org.opensaml.saml2.core.Conditions;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.NameID;
-import org.opensaml.saml2.core.RequestedAuthnContext;
-import org.opensaml.saml2.core.Subject;
-import org.opensaml.saml2.core.SubjectConfirmation;
-import org.opensaml.saml2.core.SubjectConfirmationData;
-import org.opensaml.saml2.core.impl.AuthnRequestImpl;
-import org.opensaml.saml2.metadata.AssertionConsumerService;
-import org.opensaml.saml2.metadata.AttributeConsumingService;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.NameIDFormat;
-import org.opensaml.saml2.metadata.RequestedAttribute;
-import org.opensaml.saml2.metadata.SPSSODescriptor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Base64Utils;
-
-import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
-import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper;
-import at.gv.egiz.eaaf.core.api.idp.IAuthData;
-import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
-import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface;
-import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException;
-import at.gv.egiz.eaaf.core.impl.data.Pair;
-import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
-import at.gv.egiz.eaaf.core.impl.utils.Random;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.QAANotSupportedException;
-import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator;
-import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException;
-import at.gv.egiz.eaaf.modules.pvp2.idp.exception.UnprovideableAttributeException;
-import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest;
-import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QAALevelVerifier;
-import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils;
-
-@Service("PVP2AssertionBuilder")
-public class PVP2AssertionBuilder implements PVPConstants {
-
- private static final Logger log = LoggerFactory.getLogger(PVP2AssertionBuilder.class);
- @Autowired private ILoALevelMapper loaLevelMapper;
- @Autowired private ISubjectNameIdGenerator subjectNameIdGenerator;
-
-
- /**
- * Build a PVP assertion as response for a SAML2 AttributeQuery request
- *
- * @param issuerEntityID EnitiyID, which should be used for this IDP response
- * @param attrQuery AttributeQuery request from Service-Provider
- * @param attrList List of PVP response attributes
- * @param now Current time
- * @param validTo ValidTo time of the assertion
- * @param qaaLevel QAA level of the authentication
- * @param sessionIndex SAML2 SessionIndex, which should be included *
- * @return PVP 2.1 Assertion
- * @throws PVP2Exception
- */
- public Assertion buildAssertion(String issuerEntityID, AttributeQuery attrQuery,
- List<Attribute> attrList, DateTime now, DateTime validTo, String qaaLevel, String sessionIndex) throws PVP2Exception {
-
- AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class);
- authnContextClassRef.setAuthnContextClassRef(qaaLevel);
-
- NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class);
- subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat());
- subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue());
-
- SubjectConfirmationData subjectConfirmationData = null;
-
- return buildGenericAssertion(issuerEntityID, attrQuery.getIssuer().getValue(), now,
- authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex,
- validTo);
- }
-
-
- /**
- * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest
- *
- * @param issuerEntityID EnitiyID, which should be used for this IDP response
- * @param pendingReq Current processed pendingRequest DAO
- * @param authnRequest Current processed PVP AuthnRequest
- * @param authData AuthenticationData of the user, which is already authenticated
- * @param peerEntity SAML2 EntityDescriptor of the service-provider, which receives the response
- * @param date TimeStamp
- * @param assertionConsumerService SAML2 endpoint of the service-provider, which should be used
- * @param sloInformation Single LogOut information DAO
- * @return
- * @throws PVP2Exception
- */
- public Assertion buildAssertion(String issuerEntityID, PVPSProfilePendingRequest pendingReq, AuthnRequest authnRequest,
- IAuthData authData, EntityDescriptor peerEntity, DateTime date,
- AssertionConsumerService assertionConsumerService, SLOInformationInterface sloInformation)
- throws PVP2Exception {
-
- ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration();
- AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class);
-
- //check if authn. request contains LoA
- RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext();
- if (reqAuthnContext == null) {
- authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel());
-
- } else {
- //authn. request requests LoA levels. To LoA validation
- List<AuthnContextClassRef> reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs();
-
- //get matching mode from authn. request
- String loaMatchingMode = EAAFConstants.EIDAS_LOA_MATCHING_MINIMUM;
- if (reqAuthnContext.getComparison() != null &&
- StringUtils.isNotEmpty(reqAuthnContext.getComparison().toString()))
- loaMatchingMode = reqAuthnContext.getComparison().toString();
-
- //get requested LoAs
- if (reqAuthnContextClassRefIt.size() == 0) {
- QAALevelVerifier.verifyQAALevel(authData.getEIDASQAALevel(),
- oaParam.getRequiredLoA(), loaMatchingMode);
- authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel());
-
- } else {
- List<String> eIDASLoaFromRequest = new ArrayList<String>();
- for (AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) {
- String qaa_uri = authnClassRef.getAuthnContextClassRef();
-
- if (!qaa_uri.trim().startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) {
- if (loaLevelMapper != null) {
- log.debug("Find no eIDAS LoA in AuthnReq. Start mapping process ... " );
- eIDASLoaFromRequest.add(loaLevelMapper.mapToeIDASLoA(qaa_uri.trim()));
-
- } else
- log.debug("AuthnRequest contains no eIDAS LoA. NO LoA mapper FOUND, ignore "
- + "'" + qaa_uri.trim() + "'");
- } else
- eIDASLoaFromRequest.add(qaa_uri.trim());
-
- }
-
- //stop process if no supported LoA scheme is requested
- if (eIDASLoaFromRequest.isEmpty()) {
- log.info("Authn. request contains no supported LoA level. Stop authentication process ... ");
- throw new QAANotSupportedException("No supported LoA in Authn. request");
-
- }
-
- //verifiy LoAs from request to authentication LoA
- QAALevelVerifier.verifyQAALevel(authData.getEIDASQAALevel(), eIDASLoaFromRequest , loaMatchingMode);
- authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel());
-
- }
- }
-
-
- //load SPSS decriptor from service-provider metadata
- SPSSODescriptor spSSODescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
-
- //add Attributes to Assertion
- List<Attribute> attrList = new ArrayList<Attribute>();
- if (spSSODescriptor.getAttributeConsumingServices() != null &&
- spSSODescriptor.getAttributeConsumingServices().size() > 0) {
-
- Integer aIdx = authnRequest.getAttributeConsumingServiceIndex();
- int idx = 0;
-
- AttributeConsumingService attributeConsumingService = null;
- if (aIdx != null) {
- idx = aIdx.intValue();
- attributeConsumingService = spSSODescriptor
- .getAttributeConsumingServices().get(idx);
-
- } else {
- List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor.getAttributeConsumingServices();
- for (AttributeConsumingService el : attrConsumingServiceList) {
- if (el.isDefault())
- attributeConsumingService = el;
- }
- }
-
- /*
- * TODO: maybe use first AttributeConsumingService if no is selected
- * in request or on service is marked as default
- *
- */
- if (attributeConsumingService == null ) {
- List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor.getAttributeConsumingServices();
- if (attrConsumingServiceList != null && !attrConsumingServiceList.isEmpty())
- attributeConsumingService = attrConsumingServiceList.get(0);
-
- }
-
-
- if (attributeConsumingService != null) {
- Iterator<RequestedAttribute> it = attributeConsumingService
- .getRequestAttributes().iterator();
- while (it.hasNext()) {
- RequestedAttribute reqAttribut = it.next();
- try {
- Attribute attr = PVPAttributeBuilder.buildAttribute(
- reqAttribut.getName(), oaParam, authData);
- if (attr == null) {
- if (reqAttribut.isRequired()) {
- throw new UnprovideableAttributeException(
- reqAttribut.getName());
- }
- } else {
- attrList.add(attr);
- }
-
- } catch (UnavailableAttributeException e) {
- log.info(
- "Attribute generation for "
- + reqAttribut.getFriendlyName() + " not possible.");
- if (reqAttribut.isRequired()) {
- throw new UnprovideableAttributeException(
- reqAttribut.getName());
- }
-
-
- } catch (PVP2Exception e) {
- log.info(
- "Attribute generation failed! for "
- + reqAttribut.getFriendlyName());
- if (reqAttribut.isRequired()) {
- throw new UnprovideableAttributeException(
- reqAttribut.getName());
- }
-
- } catch (Exception e) {
- log.warn(
- "General Attribute generation failed! for "
- + reqAttribut.getFriendlyName(), e);
- if (reqAttribut.isRequired()) {
- throw new UnprovideableAttributeException(
- reqAttribut.getName());
- }
-
- }
- }
- }
- }
-
- //generate subjectNameId
- NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class);
- Pair<String, String> subjectNameIdPair = subjectNameIdGenerator.generateSubjectNameId(authData, oaParam);
- subjectNameID.setValue(subjectNameIdPair.getFirst());
- subjectNameID.setNameQualifier(subjectNameIdPair.getSecond());
-
- //get NameIDFormat from request
- String nameIDFormat = NameID.TRANSIENT;
- AuthnRequest authnReq = (AuthnRequestImpl) authnRequest;
- if (authnReq.getNameIDPolicy() != null &&
- StringUtils.isNotEmpty(authnReq.getNameIDPolicy().getFormat())) {
- nameIDFormat = authnReq.getNameIDPolicy().getFormat();
-
- } else {
- //get NameIDFormat from metadata
- List<NameIDFormat> metadataNameIDFormats = spSSODescriptor.getNameIDFormats();
-
- if (metadataNameIDFormats != null) {
-
- for (NameIDFormat el : metadataNameIDFormats) {
- if (NameID.PERSISTENT.equals(el.getFormat())) {
- nameIDFormat = NameID.PERSISTENT;
- break;
-
- } else if (NameID.TRANSIENT.equals(el.getFormat()) ||
- NameID.UNSPECIFIED.equals(el.getFormat()))
- break;
-
- }
- }
- }
-
- if (NameID.TRANSIENT.equals(nameIDFormat) || NameID.UNSPECIFIED.equals(nameIDFormat)) {
- String random = Random.nextHexRandom32();
- String nameID = subjectNameID.getValue();
-
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1"));
- subjectNameID.setValue(Base64Utils.encodeToString(hash));
- subjectNameID.setNameQualifier(null);
- subjectNameID.setFormat(NameID.TRANSIENT);
-
- } catch (Exception e) {
- log.warn("PVP2 subjectNameID error", e);
- throw new ResponderErrorException("internal.03", null, e);
-
- }
-
- } else
- subjectNameID.setFormat(nameIDFormat);
-
-
- String sessionIndex = null;
-
- //if request is a reauthentication and NameIDFormat match reuse old session information
- if (StringUtils.isNotEmpty(authData.getNameID()) &&
- StringUtils.isNotEmpty(authData.getNameIDFormat()) &&
- nameIDFormat.equals(authData.getNameIDFormat())) {
- subjectNameID.setValue(authData.getNameID());
- sessionIndex = authData.getSessionIndex();
-
- }
-
- //
- if (StringUtils.isEmpty(sessionIndex))
- sessionIndex = SAML2Utils.getSecureIdentifier();
-
- SubjectConfirmationData subjectConfirmationData = SAML2Utils
- .createSAMLObject(SubjectConfirmationData.class);
- subjectConfirmationData.setInResponseTo(authnRequest.getID());
- subjectConfirmationData.setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime()));
-
- //set 'recipient' attribute in subjectConformationData
- subjectConfirmationData.setRecipient(assertionConsumerService.getLocation());
-
- //set IP address of the user machine as 'Address' attribute in subjectConformationData
- String usersIPAddress = pendingReq.getRawData(
- RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class);
- if (StringUtils.isNotEmpty(usersIPAddress))
- subjectConfirmationData.setAddress(usersIPAddress);
-
- //set SLO information
- sloInformation.setUserNameIdentifier(subjectNameID.getValue());
- sloInformation.setNameIDFormat(subjectNameID.getFormat());
- sloInformation.setSessionIndex(sessionIndex);
-
- return buildGenericAssertion(issuerEntityID, peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter());
- }
-
- /**
- *
- * @param issuer IDP EntityID
- * @param entityID Service Provider EntityID
- * @param date
- * @param authnContextClassRef
- * @param attrList
- * @param subjectNameID
- * @param subjectConfirmationData
- * @param sessionIndex
- * @param isValidTo
- * @return
- * @throws ConfigurationException
- */
-
- public Assertion buildGenericAssertion(String issuer, String entityID, DateTime date,
- AuthnContextClassRef authnContextClassRef, List<Attribute> attrList,
- NameID subjectNameID, SubjectConfirmationData subjectConfirmationData,
- String sessionIndex, DateTime isValidTo) throws ResponderErrorException {
- Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class);
-
- AuthnContext authnContext = SAML2Utils
- .createSAMLObject(AuthnContext.class);
- authnContext.setAuthnContextClassRef(authnContextClassRef);
-
- AuthnStatement authnStatement = SAML2Utils
- .createSAMLObject(AuthnStatement.class);
-
- authnStatement.setAuthnInstant(date);
- authnStatement.setSessionIndex(sessionIndex);
- authnStatement.setAuthnContext(authnContext);
-
- assertion.getAuthnStatements().add(authnStatement);
-
- AttributeStatement attributeStatement = SAML2Utils
- .createSAMLObject(AttributeStatement.class);
- attributeStatement.getAttributes().addAll(attrList);
- if (attributeStatement.getAttributes().size() > 0) {
- assertion.getAttributeStatements().add(attributeStatement);
- }
-
- Subject subject = SAML2Utils.createSAMLObject(Subject.class);
- subject.setNameID(subjectNameID);
-
- SubjectConfirmation subjectConfirmation = SAML2Utils
- .createSAMLObject(SubjectConfirmation.class);
- subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER);
- subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);
-
- subject.getSubjectConfirmations().add(subjectConfirmation);
-
- Conditions conditions = SAML2Utils.createSAMLObject(Conditions.class);
- AudienceRestriction audienceRestriction = SAML2Utils
- .createSAMLObject(AudienceRestriction.class);
- Audience audience = SAML2Utils.createSAMLObject(Audience.class);
-
- audience.setAudienceURI(entityID);
- audienceRestriction.getAudiences().add(audience);
- conditions.setNotBefore(date);
- conditions.setNotOnOrAfter(isValidTo);
-
- conditions.getAudienceRestrictions().add(audienceRestriction);
-
- assertion.setConditions(conditions);
-
- Issuer issuerObj = SAML2Utils.createSAMLObject(Issuer.class);
-
- if (issuer.endsWith("/"))
- issuer = issuer.substring(0, issuer.length()-1);
- issuerObj.setValue(issuer);
- issuerObj.setFormat(NameID.ENTITY);
-
- assertion.setIssuer(issuerObj);
- assertion.setSubject(subject);
- assertion.setID(SAML2Utils.getSecureIdentifier());
- assertion.setIssueInstant(date);
-
- return assertion;
- }
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java
new file mode 100644
index 00000000..b7b18f0f
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder;
+
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.naming.ConfigurationException;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotSupportedException;
+import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator;
+import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException;
+import at.gv.egiz.eaaf.modules.pvp2.idp.exception.UnprovideableAttributeException;
+import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QaaLevelVerifier;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+
+import org.apache.commons.lang3.StringUtils;
+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.Attribute;
+import org.opensaml.saml.saml2.core.AttributeQuery;
+import org.opensaml.saml.saml2.core.AttributeStatement;
+import org.opensaml.saml.saml2.core.Audience;
+import org.opensaml.saml.saml2.core.AudienceRestriction;
+import org.opensaml.saml.saml2.core.AuthnContext;
+import org.opensaml.saml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.AuthnStatement;
+import org.opensaml.saml.saml2.core.Conditions;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.RequestedAuthnContext;
+import org.opensaml.saml.saml2.core.Subject;
+import org.opensaml.saml.saml2.core.SubjectConfirmation;
+import org.opensaml.saml.saml2.core.SubjectConfirmationData;
+import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.NameIDFormat;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Base64Utils;
+
+@Service("PVP2AssertionBuilder")
+public class Pvp2AssertionBuilder implements PvpConstants {
+
+ private static final Logger log = LoggerFactory.getLogger(Pvp2AssertionBuilder.class);
+ @Autowired
+ private ILoALevelMapper loaLevelMapper;
+ @Autowired
+ private ISubjectNameIdGenerator subjectNameIdGenerator;
+
+ /**
+ * Build a PVP assertion as response for a SAML2 AttributeQuery request.
+ *
+ * @param issuerEntityID EnitiyID, which should be used for this IDP response
+ * @param attrQuery AttributeQuery request from Service-Provider
+ * @param attrList List of PVP response attributes
+ * @param now Current time
+ * @param validTo ValidTo time of the assertion
+ * @param qaaLevel QAA level of the authentication
+ * @param sessionIndex SAML2 SessionIndex, which should be included *
+ * @return PVP 2.1 Assertion
+ * @throws Pvp2Exception In case of an error
+ */
+ public Assertion buildAssertion(final String issuerEntityID, final AttributeQuery attrQuery,
+ final List<Attribute> attrList, final DateTime now, final DateTime validTo,
+ final String qaaLevel, final String sessionIndex) throws Pvp2Exception {
+
+ final AuthnContextClassRef authnContextClassRef =
+ Saml2Utils.createSamlObject(AuthnContextClassRef.class);
+ authnContextClassRef.setAuthnContextClassRef(qaaLevel);
+
+ final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class);
+ subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat());
+ subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue());
+
+ final SubjectConfirmationData subjectConfirmationData = null;
+
+ return buildGenericAssertion(issuerEntityID, attrQuery.getIssuer().getValue(), now,
+ authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex,
+ validTo);
+ }
+
+ /**
+ * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest.
+ *
+ * @param issuerEntityID EnitiyID, which should be used for this IDP
+ * response
+ * @param pendingReq Current processed pendingRequest DAO
+ * @param authnRequest Current processed PVP AuthnRequest
+ * @param authData AuthenticationData of the user, which is
+ * already authenticated
+ * @param peerEntity SAML2 EntityDescriptor of the
+ * service-provider, which receives the response
+ * @param date TimeStamp
+ * @param assertionConsumerService SAML2 endpoint of the service-provider, which
+ * should be used
+ * @param sloInformation Single LogOut information DAO
+ * @return PVP2 S-Profil Assertion
+ * @throws Pvp2Exception In case of an error
+ */
+ public Assertion buildAssertion(final String issuerEntityID,
+ final PvpSProfilePendingRequest pendingReq, final AuthnRequest authnRequest,
+ final IAuthData authData, final EntityDescriptor peerEntity, final DateTime date,
+ final AssertionConsumerService assertionConsumerService,
+ final SloInformationInterface sloInformation) throws Pvp2Exception {
+
+ final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration();
+ final AuthnContextClassRef authnContextClassRef =
+ Saml2Utils.createSamlObject(AuthnContextClassRef.class);
+
+ // check if authn. request contains LoA
+ final RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext();
+ if (reqAuthnContext == null) {
+ authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel());
+
+ } else {
+ // authn. request requests LoA levels. To LoA validation
+ final List<AuthnContextClassRef> reqAuthnContextClassRefIt =
+ reqAuthnContext.getAuthnContextClassRefs();
+
+ // get matching mode from authn. request
+ String loaMatchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM;
+ if (reqAuthnContext.getComparison() != null
+ && StringUtils.isNotEmpty(reqAuthnContext.getComparison().toString())) {
+ loaMatchingMode = reqAuthnContext.getComparison().toString();
+ }
+
+ // get requested LoAs
+ if (reqAuthnContextClassRefIt.size() == 0) {
+ QaaLevelVerifier.verifyQaaLevel(authData.getEidasQaaLevel(), oaParam.getRequiredLoA(),
+ loaMatchingMode);
+ authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel());
+
+ } else {
+ final List<String> eidasLoaFromRequest = new ArrayList<>();
+ for (final AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) {
+ final String qaa_uri = authnClassRef.getAuthnContextClassRef();
+
+ if (!qaa_uri.trim().startsWith(EaafConstants.EIDAS_LOA_PREFIX)) {
+ if (loaLevelMapper != null) {
+ log.debug("Find no eIDAS LoA in AuthnReq. Start mapping process ... ");
+ eidasLoaFromRequest.add(loaLevelMapper.mapToEidasLoa(qaa_uri.trim()));
+
+ } else {
+ log.debug("AuthnRequest contains no eIDAS LoA. NO LoA mapper FOUND, ignore " + "'"
+ + qaa_uri.trim() + "'");
+ }
+ } else {
+ eidasLoaFromRequest.add(qaa_uri.trim());
+ }
+
+ }
+
+ // stop process if no supported LoA scheme is requested
+ if (eidasLoaFromRequest.isEmpty()) {
+ log.info(
+ "Authn. request contains no supported LoA level. Stop authentication process ... ");
+ throw new QaaNotSupportedException("No supported LoA in Authn. request");
+
+ }
+
+ // verifiy LoAs from request to authentication LoA
+ QaaLevelVerifier.verifyQaaLevel(authData.getEidasQaaLevel(), eidasLoaFromRequest,
+ loaMatchingMode);
+ authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel());
+
+ }
+ }
+
+ // load SPSS decriptor from service-provider metadata
+ final SPSSODescriptor spSsoDescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+
+ // add Attributes to Assertion
+ final List<Attribute> attrList = new ArrayList<>();
+ if (spSsoDescriptor.getAttributeConsumingServices() != null
+ && spSsoDescriptor.getAttributeConsumingServices().size() > 0) {
+
+ final Integer aIdx = authnRequest.getAttributeConsumingServiceIndex();
+ int idx = 0;
+
+ AttributeConsumingService attributeConsumingService = null;
+ if (aIdx != null) {
+ idx = aIdx;
+ attributeConsumingService = spSsoDescriptor.getAttributeConsumingServices().get(idx);
+
+ } else {
+ final List<AttributeConsumingService> attrConsumingServiceList =
+ spSsoDescriptor.getAttributeConsumingServices();
+ for (final AttributeConsumingService el : attrConsumingServiceList) {
+ if (el.isDefault()) {
+ attributeConsumingService = el;
+ }
+ }
+ }
+
+ /*
+ * TODO: maybe use first AttributeConsumingService if no is selected in request
+ * or on service is marked as default
+ *
+ */
+ if (attributeConsumingService == null) {
+ final List<AttributeConsumingService> attrConsumingServiceList =
+ spSsoDescriptor.getAttributeConsumingServices();
+ if (attrConsumingServiceList != null && !attrConsumingServiceList.isEmpty()) {
+ attributeConsumingService = attrConsumingServiceList.get(0);
+ }
+
+ }
+
+ if (attributeConsumingService != null) {
+ final Iterator<RequestedAttribute> it =
+ attributeConsumingService.getRequestAttributes().iterator();
+ while (it.hasNext()) {
+ final RequestedAttribute reqAttribut = it.next();
+ try {
+ final Attribute attr =
+ PvpAttributeBuilder.buildAttribute(reqAttribut.getName(), oaParam, authData);
+ if (attr == null) {
+ if (reqAttribut.isRequired()) {
+ throw new UnprovideableAttributeException(reqAttribut.getName());
+ }
+ } else {
+ attrList.add(attr);
+ }
+
+ } catch (final UnavailableAttributeException e) {
+ log.info(
+ "Attribute generation for " + reqAttribut.getFriendlyName() + " not possible.");
+ if (reqAttribut.isRequired()) {
+ throw new UnprovideableAttributeException(reqAttribut.getName());
+ }
+
+ } catch (final Pvp2Exception e) {
+ log.info("Attribute generation failed! for " + reqAttribut.getFriendlyName());
+ if (reqAttribut.isRequired()) {
+ throw new UnprovideableAttributeException(reqAttribut.getName());
+ }
+
+ } catch (final Exception e) {
+ log.warn("General Attribute generation failed! for " + reqAttribut.getFriendlyName(),
+ e);
+ if (reqAttribut.isRequired()) {
+ throw new UnprovideableAttributeException(reqAttribut.getName());
+ }
+
+ }
+ }
+ }
+ }
+
+ // generate subjectNameId
+ final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class);
+ final Pair<String, String> subjectNameIdPair =
+ subjectNameIdGenerator.generateSubjectNameId(authData, oaParam);
+ subjectNameID.setValue(subjectNameIdPair.getFirst());
+ subjectNameID.setNameQualifier(subjectNameIdPair.getSecond());
+
+ // get NameIDFormat from request
+ String nameIdFormat = NameIDType.TRANSIENT;
+ final AuthnRequest authnReq = authnRequest;
+ if (authnReq.getNameIDPolicy() != null
+ && StringUtils.isNotEmpty(authnReq.getNameIDPolicy().getFormat())) {
+ nameIdFormat = authnReq.getNameIDPolicy().getFormat();
+
+ } else {
+ // get NameIDFormat from metadata
+ final List<NameIDFormat> metadataNameIdFormats = spSsoDescriptor.getNameIDFormats();
+
+ if (metadataNameIdFormats != null) {
+
+ for (final NameIDFormat el : metadataNameIdFormats) {
+ if (NameIDType.PERSISTENT.equals(el.getFormat())) {
+ nameIdFormat = NameIDType.PERSISTENT;
+ break;
+
+ } else if (NameIDType.TRANSIENT.equals(el.getFormat())
+ || NameIDType.UNSPECIFIED.equals(el.getFormat())) {
+ break;
+ }
+
+ }
+ }
+ }
+
+ if (NameIDType.TRANSIENT.equals(nameIdFormat) || NameIDType.UNSPECIFIED.equals(nameIdFormat)) {
+ final String random = Random.nextHexRandom32();
+ final String nameID = subjectNameID.getValue();
+
+ try {
+ final MessageDigest md = MessageDigest.getInstance("SHA-1");
+ final byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1"));
+ subjectNameID.setValue(Base64Utils.encodeToString(hash));
+ subjectNameID.setNameQualifier(null);
+ subjectNameID.setFormat(NameIDType.TRANSIENT);
+
+ } catch (final Exception e) {
+ log.warn("PVP2 subjectNameID error", e);
+ throw new ResponderErrorException("internal.03", null, e);
+
+ }
+
+ } else {
+ subjectNameID.setFormat(nameIdFormat);
+ }
+
+ String sessionIndex = null;
+
+ // if request is a reauthentication and NameIDFormat match reuse old session
+ // information
+ if (StringUtils.isNotEmpty(authData.getNameID())
+ && StringUtils.isNotEmpty(authData.getNameIdFormat())
+ && nameIdFormat.equals(authData.getNameIdFormat())) {
+ subjectNameID.setValue(authData.getNameID());
+ sessionIndex = authData.getSessionIndex();
+
+ }
+
+ //
+ if (StringUtils.isEmpty(sessionIndex)) {
+ sessionIndex = Saml2Utils.getSecureIdentifier();
+ }
+
+ final SubjectConfirmationData subjectConfirmationData =
+ Saml2Utils.createSamlObject(SubjectConfirmationData.class);
+ subjectConfirmationData.setInResponseTo(authnRequest.getID());
+ subjectConfirmationData
+ .setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime()));
+
+ // set 'recipient' attribute in subjectConformationData
+ subjectConfirmationData.setRecipient(assertionConsumerService.getLocation());
+
+ // set IP address of the user machine as 'Address' attribute in
+ // subjectConformationData
+ final String usersIpAddress =
+ pendingReq.getRawData(RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class);
+ if (StringUtils.isNotEmpty(usersIpAddress)) {
+ subjectConfirmationData.setAddress(usersIpAddress);
+ }
+
+ // set SLO information
+ sloInformation.setUserNameIdentifier(subjectNameID.getValue());
+ sloInformation.setNameIdFormat(subjectNameID.getFormat());
+ sloInformation.setSessionIndex(sessionIndex);
+
+ return buildGenericAssertion(issuerEntityID, peerEntity.getEntityID(), date,
+ authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex,
+ subjectConfirmationData.getNotOnOrAfter());
+ }
+
+ /**
+ * Build generic part of PVP S-Profile Assertion.
+ *
+ * @param issuer IDP EntityID
+ * @param entityID Service Provider EntityID
+ * @param date Timestamp
+ * @param authnContextClassRef SAML2 AuthnContextClassReference
+ * @param attrList List of attributes
+ * @param subjectNameID SubjectNameId
+ * @param subjectConfirmationData SubjectConfirmationInformation
+ * @param sessionIndex SessionIndex
+ * @param isValidTo ValidTo Timestamp
+ * @return PVP S-Profile Assertion
+ * @throws ConfigurationException In case on an error
+ */
+
+ public Assertion buildGenericAssertion(String issuer, final String entityID, final DateTime date,
+ final AuthnContextClassRef authnContextClassRef, final List<Attribute> attrList,
+ final NameID subjectNameID, final SubjectConfirmationData subjectConfirmationData,
+ final String sessionIndex, final DateTime isValidTo) throws ResponderErrorException {
+ final Assertion assertion = Saml2Utils.createSamlObject(Assertion.class);
+
+ final AuthnContext authnContext = Saml2Utils.createSamlObject(AuthnContext.class);
+ authnContext.setAuthnContextClassRef(authnContextClassRef);
+
+ final AuthnStatement authnStatement = Saml2Utils.createSamlObject(AuthnStatement.class);
+
+ authnStatement.setAuthnInstant(date);
+ authnStatement.setSessionIndex(sessionIndex);
+ authnStatement.setAuthnContext(authnContext);
+
+ assertion.getAuthnStatements().add(authnStatement);
+
+ final AttributeStatement attributeStatement =
+ Saml2Utils.createSamlObject(AttributeStatement.class);
+ attributeStatement.getAttributes().addAll(attrList);
+ if (attributeStatement.getAttributes().size() > 0) {
+ assertion.getAttributeStatements().add(attributeStatement);
+ }
+
+ final Subject subject = Saml2Utils.createSamlObject(Subject.class);
+ subject.setNameID(subjectNameID);
+
+ final SubjectConfirmation subjectConfirmation =
+ Saml2Utils.createSamlObject(SubjectConfirmation.class);
+ subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER);
+ subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);
+
+ subject.getSubjectConfirmations().add(subjectConfirmation);
+
+ final Conditions conditions = Saml2Utils.createSamlObject(Conditions.class);
+ final AudienceRestriction audienceRestriction =
+ Saml2Utils.createSamlObject(AudienceRestriction.class);
+ final Audience audience = Saml2Utils.createSamlObject(Audience.class);
+
+ audience.setAudienceURI(entityID);
+ audienceRestriction.getAudiences().add(audience);
+ conditions.setNotBefore(date);
+ conditions.setNotOnOrAfter(isValidTo);
+
+ conditions.getAudienceRestrictions().add(audienceRestriction);
+
+ assertion.setConditions(conditions);
+
+ final Issuer issuerObj = Saml2Utils.createSamlObject(Issuer.class);
+
+ if (issuer.endsWith("/")) {
+ issuer = issuer.substring(0, issuer.length() - 1);
+ }
+ issuerObj.setValue(issuer);
+ issuerObj.setFormat(NameIDType.ENTITY);
+
+ assertion.setIssuer(issuerObj);
+ assertion.setSubject(subject);
+ assertion.setID(Saml2Utils.getSecureIdentifier());
+ assertion.setIssueInstant(date);
+
+ return assertion;
+ }
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
index cda12a62..c3c68e20 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -1 +1 @@
-at.gv.egiz.eaaf.modules.pvp2.idp.PVP2SProfileIDPSpringResourceProvider \ No newline at end of file
+at.gv.egiz.eaaf.modules.pvp2.idp.Pvp2SProfileIdpSpringResourceProvider \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml
index b01a09ff..d29b5aba 100644
--- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml
@@ -1,22 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!--
- -->
-
<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
-
- <bean id="PVP2AssertionBuilder"
- class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.PVP2AssertionBuilder" />
-
- <bean id="PVPSProfilePendingRequest"
- class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest"
- scope="prototype"/>
-
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="PVP2AssertionBuilder"
+ class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.Pvp2AssertionBuilder" />
+
+ <bean id="PVPSProfilePendingRequest"
+ class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest"
+ scope="prototype" />
+
</beans> \ No newline at end of file
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
new file mode 100644
index 00000000..b2e528c4
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java
@@ -0,0 +1,156 @@
+package at.gv.egiz.eaaf.modules.pvp2.idp.test;
+
+import java.io.IOException;
+
+import javax.xml.transform.TransformerException;
+
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.exception.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;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.RequestAbstractType;
+import org.opensaml.saml.saml2.core.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.w3c.dom.Element;
+
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"})
+@TestPropertySource(
+ locations = {"/config/config_1.props"})
+public class AuthnResponseBuilderTest {
+
+ @Autowired private DummyAuthConfig authConfig;
+ @Autowired private PvpMetadataResolverFactory metadataResolverFactory;
+ @Autowired private SamlVerificationEngine verifyEngine;
+ @Autowired private DummyCredentialProvider credentialProvider;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ @Test
+ public void encryptedAssertion() throws InvalidAssertionEncryptionException, Pvp2MetadataException,
+ XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException {
+ final String issuerEntityID = RandomStringUtils.randomAlphabetic(15);
+
+ final IPvp2MetadataProvider metadataProvider =
+ metadataResolverFactory.createMetadataProvider(
+ "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null);
+
+ final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"));
+ authnReq.setID("_" + RandomStringUtils.randomAlphanumeric(10));
+
+ final Assertion assertion = (Assertion) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ PostBindingTest.class.getResourceAsStream("/data/Assertion_1.xml"));
+
+ //build response
+ final DateTime now = DateTime.now();
+ final Response response = AuthResponseBuilder.buildResponse(
+ metadataProvider, issuerEntityID, authnReq,
+ now, assertion, authConfig);
+
+
+ //validate
+ Assert.assertNotNull("SAML2 response is null", response);
+ Assert.assertTrue("Assertion not null", response.getAssertions().isEmpty());
+ Assert.assertNotNull("Enc. assertion is null", response.getEncryptedAssertions());
+ Assert.assertFalse("Enc. assertion is empty", response.getEncryptedAssertions().isEmpty());
+ Assert.assertEquals("# enc. assertions wrong", 1, response.getEncryptedAssertions().size());
+
+ Assert.assertEquals("InResponseTo", authnReq.getID(), response.getInResponseTo());
+ Assert.assertEquals("Issuer EntityId", issuerEntityID, response.getIssuer().getValue());
+ Assert.assertNotNull("ResponseId is null", response.getID());
+ Assert.assertFalse("ResponseId is emptry", response.getID().isEmpty());
+
+ final Element responseElement = XMLObjectSupport.getMarshaller(response).marshall(response);
+ final String xmlResp = DomUtils.serializeNode(responseElement);
+ Assert.assertNotNull("XML response is null", xmlResp);
+ Assert.assertFalse("XML response is empty", xmlResp.isEmpty());
+
+ }
+
+ @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..c5fc0f13
--- /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,52 @@
+package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy;
+
+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.modules.pvp2.api.IPvp2BasicConfiguration;
+
+import org.opensaml.saml.saml2.metadata.ContactPerson;
+import org.opensaml.saml.saml2.metadata.Organization;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class DummyPvpConfiguration implements IPvp2BasicConfiguration {
+
+ @Autowired private IConfiguration basicConfig;
+
+ @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 String 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;
+ }
+
+ @Override
+ public IConfiguration getBasicConfiguration() {
+ return basicConfig;
+ }
+
+}
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/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props
new file mode 100644
index 00000000..164b8807
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props
@@ -0,0 +1,12 @@
+keystore.path=classpath:/data/junit.jks
+keystore.pass=password
+key.metadata.alias=meta
+key.metadata.pass=password
+key.sig.alias=sig
+key.sig.pass=password
+key.enc.alias=
+key.enc.pass=
+
+client.http.connection.timeout.socket=2
+client.http.connection.timeout.connection=2
+client.http.connection.timeout.request=2 \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props
new file mode 100644
index 00000000..60cecebb
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props
@@ -0,0 +1,12 @@
+keystore.path=classpath:/data/junit.jks
+keystore.pass=password
+key.metadata.alias=shibboleth-sign
+key.metadata.pass=password
+key.sig.alias=shibboleth-sign
+key.sig.pass=password
+key.enc.alias=
+key.enc.pass=
+
+client.http.connection.timeout.socket=2
+client.http.connection.timeout.connection=2
+client.http.connection.timeout.request=2 \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml
new file mode 100644
index 00000000..7c45b5fa
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0">
+ <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer>
+ <saml2:Subject>
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml
new file mode 100644
index 00000000..ef35ea92
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer>
+ <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID>
+ </saml2:Subject>
+ <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
+ <saml2p:RequestedAuthnContext>
+ <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef>
+ </saml2p:RequestedAuthnContext>
+</saml2p:AuthnRequest>
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks
new file mode 100644
index 00000000..b5262cb8
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks
Binary files differ
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml
new file mode 100644
index 00000000..7fdbef90
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="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: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>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>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/>
+ <md:AttributeConsumingService index="0" isDefault="true">
+ <md:ServiceName xml:lang="en">Default Service</md:ServiceName>
+ <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ </md:AttributeConsumingService>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml
new file mode 100644
index 00000000..99552053
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="dummyAuthConfig"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" />
+
+ <bean id="dummyVelocityGuiBuilder"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" />
+
+ <bean id="dummyGuiBuilderConfigFactory"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" />
+
+ <bean id="httpClientFactory"
+ class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" />
+
+ <bean id="dummyRevisionLogger"
+ class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" />
+
+ <bean id="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
new file mode 100644
index 00000000..2bddd629
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <import resource="test_eaaf_core.beans.xml"/>
+ <import resource="classpath:/eaaf_pvp.beans.xml"/>
+ <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/pom.xml b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml
index d2157a45..69eb26ab 100644
--- a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml
+++ b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>at.gv.egiz.eaaf</groupId>
<artifactId>eaaf_modules</artifactId>
- <version>1.0.13.2</version>
+ <version>1.1.0</version>
</parent>
<artifactId>eaaf_module_pvp2_sp</artifactId>
<name>eaaf_module_pvp2_sp</name>
@@ -32,11 +32,23 @@
<scope>provided</scope>
</dependency>
+ <!-- Only for testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_core_utils</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
</dependencies>
<build>
@@ -54,21 +66,20 @@
</plugin>
<!-- enable co-existence of testng and junit -->
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>${surefire.version}</version>
- <configuration>
- <threadCount>1</threadCount>
- <argLine>--add-modules java.xml.bind</argLine>
- </configuration>
- <dependencies>
- <dependency>
- <groupId>org.apache.maven.surefire</groupId>
- <artifactId>surefire-junit47</artifactId>
- <version>${surefire.version}</version>
- </dependency>
- </dependencies>
- </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
</plugins>
</build>
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java
new file mode 100644
index 00000000..7535e013
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.sp;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+public class Pvp2SProfileSpSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "EAAF PVP2 S-Profile Service-Provider SpringResourceProvider";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource sl20AuthConfig =
+ new ClassPathResource("/eaaf_pvp_sp.beans.xml", Pvp2SProfileSpSpringResourceProvider.class);
+
+ return new Resource[] { sl20AuthConfig };
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java
deleted file mode 100644
index b8a8e796..00000000
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.sp.api;
-
-import java.util.List;
-
-import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.xml.security.credential.Credential;
-import org.w3c.dom.Element;
-
-import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute;
-
-/**
- * @author tlenz
- *
- */
-public interface IPVPAuthnRequestBuilderConfiguruation {
-
- /**
- * Defines a unique name for this PVP Service-provider, which is used for logging
- *
- * @return
- */
- public String getSPNameForLogging();
-
- /**
- * If true, the SAML2 isPassive flag is set in the AuthnRequest
- *
- * @return
- */
- public Boolean isPassivRequest();
-
- /**
- * Define the ID of the AssertionConsumerService,
- * which defines the required attributes in service-provider metadata.
- *
- * @return
- */
- public Integer getAssertionConsumerServiceId();
-
- /**
- * Define the SAML2 EntityID of the service provider.
- *
- * @return
- */
- public String getSPEntityID();
-
- /**
- * Define the SAML2 NameIDPolicy
- *
- * @return Service-Provider EntityID, but never null
- */
- public String getNameIDPolicyFormat();
-
- /**
- * Define the AuthnContextClassRefernece of this request
- *
- * Example:
- * http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3
- * http://www.stork.gov.eu/1.0/citizenQAALevel/4
- *
- *
- * @return
- */
- public String getAuthnContextClassRef();
-
- /**
- * Define the AuthnContextComparison model, which should be used
- *
- * @return
- */
- public AuthnContextComparisonTypeEnumeration getAuthnContextComparison();
-
-
- /**
- * Define the credential, which should be used to sign the AuthnRequest
- *
- * @return
- */
- public Credential getAuthnRequestSigningCredential();
-
-
- /**
- * Define the SAML2 EntityDescriptor of the IDP, which should receive the AuthnRequest
- *
- * @return Credential, but never null.
- */
- public EntityDescriptor getIDPEntityDescriptor();
-
- /**
- * Set the SAML2 NameIDPolicy allow-creation flag
- *
- * @return EntityDescriptor, but never null.
- */
- public boolean getNameIDPolicyAllowCreation();
-
-
- /**
- * Set the requested SubjectNameID
- *
- * @return SubjectNameID, or null if no SubjectNameID should be used
- */
- public String getSubjectNameID();
-
- /**
- * Define the qualifier of the <code>SubjectNameID</code>
- * <br><br>
- * Like: 'urn:publicid:gv.at:cdid+BF'
- *
- * @return qualifier, or null if no qualifier should be set
- */
- public String getSubjectNameIDQualifier();
-
- /**
- * Define the format of the subjectNameID, which is included in authn-request
- *
- *
- * @return nameIDFormat, of SAML2 'transient' if nothing is defined
- */
- public String getSubjectNameIDFormat();
-
- /**
- * Define a SP specific SAML2 requestID
- *
- * @return requestID, or null if the requestID should be generated automatically
- */
- public String getRequestID();
-
- /**
- * Defines the 'method' attribute in 'SubjectConformation' element
- *
- * @return method, or null if no method should set
- */
- public String getSubjectConformationMethode();
-
- /**
- * Define the information, which should be added as 'subjectConformationDate'
- * in 'SubjectConformation' element
- *
- * @return subjectConformation information or null if no subjectConformation should be set
- */
- public Element getSubjectConformationDate();
-
-
- /**
- * Get the EntityId of the SP in case of a SAML2 proxy use-case
- *
- * @return
- */
- public String getScopeRequesterId();
-
-
- /**
- * Get a FriendlyName for the SP that sends the request
- *
- * @return
- */
- public String getProviderName();
-
-
- /**
- * Get a Set of SAML2 attributes that are requested by using SAML2 requested attributes
- * <br>
- * <b>Info:</b> Attributes are requested by using eIDAS SAML2 extension for requested attributes
- *
- * @return
- */
- public List<EAAFRequestedAttribute> getRequestedAttributes();
-
-}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java
new file mode 100644
index 00000000..597507f3
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.sp.api;
+
+import java.util.List;
+
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+
+import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.w3c.dom.Element;
+
+/**
+ * Configuration of a PVP2 S-Profile authentication-request builder.
+ *
+ * @author tlenz
+ *
+ */
+public interface IPvpAuthnRequestBuilderConfiguruation {
+
+ /**
+ * Defines a unique name for this PVP Service-provider, which is used for
+ * logging.
+ *
+ * @return
+ */
+ String getSpNameForLogging();
+
+ /**
+ * If true, the SAML2 isPassive flag is set in the AuthnRequest.
+ *
+ * @return
+ */
+ Boolean isPassivRequest();
+
+ /**
+ * Define the ID of the AssertionConsumerService, which defines the required
+ * attributes in service-provider metadata.
+ *
+ * @return
+ */
+ Integer getAssertionConsumerServiceId();
+
+ /**
+ * Define the SAML2 EntityID of the service provider.
+ *
+ * @return
+ */
+ String getSpEntityID();
+
+ /**
+ * Define the SAML2 NameIDPolicy.
+ *
+ * @return Service-Provider EntityID, but never null
+ */
+ String getNameIdPolicyFormat();
+
+ /**
+ * Define the AuthnContextClassRefernece of this request.
+ *
+ * <p>
+ * Example: http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3
+ * http://www.stork.gov.eu/1.0/citizenQAALevel/4
+ * </p>
+ *
+ * @return
+ */
+ String getAuthnContextClassRef();
+
+ /**
+ * Define the AuthnContextComparison model, which should be used.
+ *
+ * @return
+ */
+ AuthnContextComparisonTypeEnumeration getAuthnContextComparison();
+
+ /**
+ * Define the credential, which should be used to sign the AuthnRequest.
+ *
+ * @return
+ */
+ EaafX509Credential getAuthnRequestSigningCredential();
+
+ /**
+ * Define the SAML2 EntityDescriptor of the IDP, which should receive the
+ * AuthnRequest.
+ *
+ * @return Credential, but never null.
+ */
+ EntityDescriptor getIdpEntityDescriptor();
+
+ /**
+ * Set the SAML2 NameIDPolicy allow-creation flag.
+ *
+ * @return EntityDescriptor, but never null.
+ */
+ boolean getNameIdPolicyAllowCreation();
+
+ /**
+ * Set the requested SubjectNameID.
+ *
+ * @return SubjectNameID, or null if no SubjectNameID should be used
+ */
+ String getSubjectNameID();
+
+ /**
+ * Define the qualifier of the <code>SubjectNameID</code> <br>
+ * <br>
+ * Like: 'urn:publicid:gv.at:cdid+BF'
+ *
+ * @return qualifier, or null if no qualifier should be set
+ */
+ String getSubjectNameIdQualifier();
+
+ /**
+ * Define the format of the subjectNameID, which is included in authn-request.
+ *
+ *
+ * @return nameIDFormat, of SAML2 'transient' if nothing is defined
+ */
+ String getSubjectNameIdFormat();
+
+ /**
+ * Define a SP specific SAML2 requestID.
+ *
+ * @return requestID, or null if the requestID should be generated automatically
+ */
+ String getRequestID();
+
+ /**
+ * Defines the 'method' attribute in 'SubjectConformation' element.
+ *
+ * @return method, or null if no method should set
+ */
+ String getSubjectConformationMethode();
+
+ /**
+ * Define the information, which should be added as 'subjectConformationDate' in
+ * 'SubjectConformation' element.
+ *
+ * @return subjectConformation information or null if no subjectConformation
+ * should be set
+ */
+ Element getSubjectConformationDate();
+
+ /**
+ * Get the EntityId of the SP in case of a SAML2 proxy use-case.
+ *
+ * @return
+ */
+ String getScopeRequesterId();
+
+ /**
+ * Get a FriendlyName for the SP that sends the request.
+ *
+ * @return
+ */
+ String getProviderName();
+
+ /**
+ * Get a Set of SAML2 attributes that are requested by using SAML2 requested
+ * attributes. <br>
+ * <b>Info:</b> Attributes are requested by using eIDAS SAML2 extension for
+ * requested attributes
+ *
+ * @return
+ */
+ List<EaafRequestedAttribute> getRequestedAttributes();
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java
index 3afcc65d..4411d9c6 100644
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java
@@ -1,56 +1,40 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.sp.exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-/**
- * @author tlenz
- *
- */
-public class AssertionAttributeExtractorExeption extends PVP2Exception {
-
- /**
- *
- */
- private static final long serialVersionUID = -6459000942830951492L;
-
- public AssertionAttributeExtractorExeption(String attributeName) {
- super("Parse PVP2.1 assertion FAILED: Attribute " + attributeName
- + " can not extract.", null);
- }
-
- public AssertionAttributeExtractorExeption(String messageId,
- Object[] parameters) {
- super(messageId, parameters);
- }
-
- public AssertionAttributeExtractorExeption() {
- super("Parse PVP2.1 assertion FAILED. Interfederation not possible", null);
- }
+public class AssertionAttributeExtractorExeption extends Pvp2Exception {
+
+ private static final long serialVersionUID = -6459000942830951492L;
+
+ public AssertionAttributeExtractorExeption(final String attributeName) {
+ super("Parse PVP2.1 assertion FAILED: Attribute " + attributeName + " can not extract.", null);
+ }
+
+ public AssertionAttributeExtractorExeption(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
+
+ public AssertionAttributeExtractorExeption() {
+ super("Parse PVP2.1 assertion FAILED. Interfederation not possible", null);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java
index 5766aab0..03fae599 100644
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java
@@ -1,53 +1,37 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.sp.exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-/**
- * @author tlenz
- *
- */
-public class AssertionValidationExeption extends PVP2Exception {
+public class AssertionValidationExeption extends Pvp2Exception {
- private static final long serialVersionUID = -3987805399122286259L;
+ private static final long serialVersionUID = -3987805399122286259L;
- public AssertionValidationExeption(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
+ public AssertionValidationExeption(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
- /**
- * @param string
- * @param object
- * @param e
- */
- public AssertionValidationExeption(String string, Object[] parameters,
- Throwable e) {
- super(string, parameters, e);
- }
+ public AssertionValidationExeption(final String string, final Object[] parameters,
+ final Throwable e) {
+ super(string, parameters, e);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java
index 9fdffaf4..251ba759 100644
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java
@@ -1,53 +1,35 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
package at.gv.egiz.eaaf.modules.pvp2.sp.exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-/**
- * @author tlenz
- *
- */
-public class AuthnRequestBuildException extends PVP2Exception {
+public class AuthnRequestBuildException extends Pvp2Exception {
- /**
- *
- */
- private static final long serialVersionUID = -1375451065455859354L;
+ private static final long serialVersionUID = -1375451065455859354L;
- /**
- * @param messageId
- * @param parameters
- */
- public AuthnRequestBuildException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
+ public AuthnRequestBuildException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
- public AuthnRequestBuildException(String messageId, Object[] parameters, Throwable e) {
- super(messageId, parameters, e);
- }
+ public AuthnRequestBuildException(final String messageId, final Object[] parameters, final Throwable e) {
+ super(messageId, parameters, e);
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java
index 9d2ec046..44fbf40f 100644
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java
@@ -1,54 +1,37 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.sp.exception;
-import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception;
-/**
- * @author tlenz
- *
- */
-public class AuthnResponseValidationException extends PVP2Exception {
+public class AuthnResponseValidationException extends Pvp2Exception {
+
+ private static final long serialVersionUID = 8023812861029406575L;
- /**
- *
- */
- private static final long serialVersionUID = 8023812861029406575L;
+ public AuthnResponseValidationException(final String messageId, final Object[] parameters) {
+ super(messageId, parameters);
+ }
- /**
- * @param messageId
- * @param parameters
- */
- public AuthnResponseValidationException(String messageId, Object[] parameters) {
- super(messageId, parameters);
- }
-
- public AuthnResponseValidationException(String messageId, Object[] parameters, Throwable e) {
- super(messageId, parameters, e);
- }
+ public AuthnResponseValidationException(final String messageId, final Object[] parameters,
+ final Throwable e) {
+ super(messageId, parameters, e);
+ }
}
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
deleted file mode 100644
index e8cdd1f7..00000000
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
- *
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * https://joinup.ec.europa.eu/news/understanding-eupl-v12
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-package at.gv.egiz.eaaf.modules.pvp2.sp.impl;
-
-import java.security.NoSuchAlgorithmException;
-import java.util.List;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.common.Extensions;
-import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml2.core.AuthnRequest;
-import org.opensaml.saml2.core.Issuer;
-import org.opensaml.saml2.core.NameID;
-import org.opensaml.saml2.core.NameIDPolicy;
-import org.opensaml.saml2.core.NameIDType;
-import org.opensaml.saml2.core.RequestedAuthnContext;
-import org.opensaml.saml2.core.RequesterID;
-import org.opensaml.saml2.core.Scoping;
-import org.opensaml.saml2.core.Subject;
-import org.opensaml.saml2.core.SubjectConfirmation;
-import org.opensaml.saml2.core.SubjectConfirmationData;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.SingleSignOnService;
-import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.xml.security.SecurityException;
-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.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;
-
-/**
- * @author tlenz
- *
- */
-@Service("pvpAuthnRequestBuilder")
-public class PVPAuthnRequestBuilder {
- private static final Logger log = LoggerFactory.getLogger(PVPAuthnRequestBuilder.class);
-
-
- @Autowired(required=true) ApplicationContext springContext;
-
-
- /**
- * Build a PVP2.x specific authentication request
- *
- * @param pendingReq Currently processed pendingRequest
- * @param config AuthnRequest builder configuration, never null
- * @param idpEntity SAML2 EntityDescriptor of the IDP, which receive this AuthnRequest, never null
- * @param httpResp
- * @throws NoSuchAlgorithmException
- * @throws SecurityException
- * @throws PVP2Exception
- * @throws MessageEncodingException
- */
- public void buildAuthnRequest(IRequest pendingReq, IPVPAuthnRequestBuilderConfiguruation config,
- HttpServletResponse httpResp) throws NoSuchAlgorithmException, MessageEncodingException, PVP2Exception, SecurityException {
- //get IDP Entity element from config
- EntityDescriptor idpEntity = config.getIDPEntityDescriptor();
-
- AuthnRequest authReq = SAML2Utils
- .createSAMLObject(AuthnRequest.class);
-
- //select SingleSignOn Service endpoint from IDP metadata
- SingleSignOnService endpoint = null;
- for (SingleSignOnService sss :
- idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) {
-
- // use POST binding as default if it exists
- if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
- endpoint = sss;
-
- } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)
- && endpoint == null )
- endpoint = sss;
-
- }
-
- if (endpoint == null) {
- log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID()
- + " does not support POST or Redirect Binding.");
- throw new AuthnRequestBuildException("sp.pvp2.00", new Object[]{config.getSPNameForLogging(), idpEntity.getEntityID()});
-
- } else
- authReq.setDestination(endpoint.getLocation());
-
-
- //set basic AuthnRequest information
- String reqID = config.getRequestID();
- if (StringUtils.isNotEmpty(reqID))
- authReq.setID(reqID);
-
- else {
- SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator();
- authReq.setID(gen.generateIdentifier());
-
- }
-
- authReq.setIssueInstant(new DateTime());
-
- //set isPassive flag
- if (config.isPassivRequest() == null)
- authReq.setIsPassive(false);
- else
- authReq.setIsPassive(config.isPassivRequest());
-
- //set EntityID of the service provider
- Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
- issuer.setFormat(NameIDType.ENTITY);
- issuer.setValue(config.getSPEntityID());
- authReq.setIssuer(issuer);
-
- //set AssertionConsumerService ID
- if (config.getAssertionConsumerServiceId() != null)
- authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId());
-
- //set NameIDPolicy
- if (config.getNameIDPolicyFormat() != null) {
- NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class);
- policy.setAllowCreate(config.getNameIDPolicyAllowCreation());
- policy.setFormat(config.getNameIDPolicyFormat());
- authReq.setNameIDPolicy(policy);
- }
-
- //set requested QAA level
- if (config.getAuthnContextClassRef() != null) {
- RequestedAuthnContext reqAuthContext = SAML2Utils.createSAMLObject(RequestedAuthnContext.class);
- AuthnContextClassRef authnClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class);
-
- authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef());
-
- if (config.getAuthnContextComparison() == null)
- reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);
- else
- reqAuthContext.setComparison(config.getAuthnContextComparison());
-
- reqAuthContext.getAuthnContextClassRefs().add(authnClassRef);
- authReq.setRequestedAuthnContext(reqAuthContext);
- }
-
- //set request Subject element
- if (StringUtils.isNotEmpty(config.getSubjectNameID())) {
- Subject reqSubject = SAML2Utils.createSAMLObject(Subject.class);
- NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class);
-
- subjectNameID.setValue(config.getSubjectNameID());
- if (StringUtils.isNotEmpty(config.getSubjectNameIDQualifier()))
- subjectNameID.setNameQualifier(config.getSubjectNameIDQualifier());
-
- if (StringUtils.isNotEmpty(config.getSubjectNameIDFormat()))
- subjectNameID.setFormat(config.getSubjectNameIDFormat());
- else
- subjectNameID.setFormat(NameID.TRANSIENT);
-
- reqSubject.setNameID(subjectNameID);
-
- if (config.getSubjectConformationDate() != null) {
- SubjectConfirmation subjectConformation = SAML2Utils.createSAMLObject(SubjectConfirmation.class);
- SubjectConfirmationData subjectConformDate = SAML2Utils.createSAMLObject(SubjectConfirmationData.class);
- subjectConformation.setSubjectConfirmationData(subjectConformDate);
- reqSubject.getSubjectConfirmations().add(subjectConformation );
-
- if (config.getSubjectConformationMethode() != null)
- subjectConformation.setMethod(config.getSubjectConformationMethode());
-
- subjectConformDate.setDOM(config.getSubjectConformationDate());
-
- }
-
- authReq.setSubject(reqSubject );
-
- }
-
-
- //set ProviderName
- if (StringUtils.isNotEmpty(config.getProviderName()))
- authReq.setProviderName(config.getProviderName());
-
- //set RequesterId in case of proxy mode
- if (StringUtils.isNotEmpty(config.getScopeRequesterId())) {
- Scoping scope = SAML2Utils.createSAMLObject(Scoping.class);
- RequesterID requesterId = SAML2Utils.createSAMLObject(RequesterID.class);
- requesterId.setRequesterID(config.getScopeRequesterId());
- scope.getRequesterIDs().add(requesterId );
- authReq.setScoping(scope );
-
- }
-
- //add optional requested attributes
- if (config.getRequestedAttributes() != null) {
- List<EAAFRequestedAttribute> reqAttr = config.getRequestedAttributes();
- Extensions extenstions = new EAAFRequestExtensionBuilder().buildObject();
- EAAFRequestedAttributes reqAttributs = SAML2Utils.createSAMLObject(EAAFRequestedAttributes.class);
- reqAttributs.getAttributes().addAll(reqAttr);
- extenstions.getUnknownXMLObjects().add(reqAttributs);
- authReq.setExtensions(extenstions );
-
- }
-
- //select message encoder
- IEncoder binding = null;
- if (endpoint.getBinding().equals(
- SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
- binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class);
-
- } else if (endpoint.getBinding().equals(
- SAMLConstants.SAML2_POST_BINDING_URI)) {
- binding = springContext.getBean("PVPPOSTBinding", PostBinding.class);
-
- }
-
- //encode message
- binding.encodeRequest(null, httpResp, authReq,
- endpoint.getLocation(), pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq);
- }
-
-}
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
new file mode 100644
index 00000000..752386a0
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.gv.egiz.eaaf.modules.pvp2.sp.impl;
+
+import java.security.NoSuchAlgorithmException;
+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;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.Extensions;
+import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.core.NameIDPolicy;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.RequestedAuthnContext;
+import org.opensaml.saml.saml2.core.RequesterID;
+import org.opensaml.saml.saml2.core.Scoping;
+import org.opensaml.saml.saml2.core.Subject;
+import org.opensaml.saml.saml2.core.SubjectConfirmation;
+import org.opensaml.saml.saml2.core.SubjectConfirmationData;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.SingleSignOnService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+
+import net.shibboleth.utilities.java.support.security.SecureRandomIdentifierGenerationStrategy;
+
+/**
+ * PVP2 S-Profil Authentication-Request builder-implementation.
+ *
+ * @author tlenz
+ *
+ */
+public class PvpAuthnRequestBuilder {
+ private static final Logger log = LoggerFactory.getLogger(PvpAuthnRequestBuilder.class);
+
+ @Autowired(required = true)
+ ApplicationContext springContext;
+
+ /**
+ * Build a PVP2.x specific authentication request
+ *
+ * @param pendingReq Currently processed pendingRequest
+ * @param config AuthnRequest builder configuration, never null
+ * @param httpResp http response object
+ * @throws NoSuchAlgorithmException In case of error
+ * @throws SecurityException In case of error
+ * @throws Pvp2Exception In case of error
+ * @throws MessageEncodingException In case of error
+ */
+ public void buildAuthnRequest(final IRequest pendingReq,
+ final IPvpAuthnRequestBuilderConfiguruation config, final HttpServletResponse httpResp)
+ throws NoSuchAlgorithmException, MessageEncodingException, Pvp2Exception, SecurityException {
+ // get IDP Entity element from config
+ final EntityDescriptor idpEntity = config.getIdpEntityDescriptor();
+
+ final AuthnRequest authReq = Saml2Utils.createSamlObject(AuthnRequest.class);
+
+ // select SingleSignOn Service endpoint from IDP metadata
+ SingleSignOnService endpoint = null;
+ for (final SingleSignOnService sss : idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)
+ .getSingleSignOnServices()) {
+
+ // use POST binding as default if it exists
+ if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
+ endpoint = sss;
+
+ } else if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)
+ && endpoint == null) {
+ endpoint = sss;
+ }
+
+ }
+
+ if (endpoint == null) {
+ log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID()
+ + " does not support POST or Redirect Binding.");
+ throw new AuthnRequestBuildException("sp.pvp2.00",
+ new Object[] { config.getSpNameForLogging(), idpEntity.getEntityID() });
+
+ } else {
+ authReq.setDestination(endpoint.getLocation());
+ }
+
+ // set basic AuthnRequest information
+ final String reqID = config.getRequestID();
+ if (StringUtils.isNotEmpty(reqID)) {
+ authReq.setID(reqID);
+ } else {
+ final SecureRandomIdentifierGenerationStrategy gen = new SecureRandomIdentifierGenerationStrategy();
+ authReq.setID(gen.generateIdentifier());
+
+ }
+
+ authReq.setIssueInstant(new DateTime());
+
+ // set isPassive flag
+ if (config.isPassivRequest() == null) {
+ authReq.setIsPassive(false);
+ } else {
+ authReq.setIsPassive(config.isPassivRequest());
+ }
+
+ // set EntityID of the service provider
+ final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class);
+ issuer.setFormat(NameIDType.ENTITY);
+ issuer.setValue(config.getSpEntityID());
+ authReq.setIssuer(issuer);
+
+ // set AssertionConsumerService ID
+ if (config.getAssertionConsumerServiceId() != null) {
+ authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId());
+ }
+
+ // set NameIDPolicy
+ if (config.getNameIdPolicyFormat() != null) {
+ final NameIDPolicy policy = Saml2Utils.createSamlObject(NameIDPolicy.class);
+ policy.setAllowCreate(config.getNameIdPolicyAllowCreation());
+ policy.setFormat(config.getNameIdPolicyFormat());
+ authReq.setNameIDPolicy(policy);
+ }
+
+ // set requested QAA level
+ if (config.getAuthnContextClassRef() != null) {
+ final RequestedAuthnContext reqAuthContext =
+ Saml2Utils.createSamlObject(RequestedAuthnContext.class);
+ final AuthnContextClassRef authnClassRef =
+ Saml2Utils.createSamlObject(AuthnContextClassRef.class);
+
+ authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef());
+
+ if (config.getAuthnContextComparison() == null) {
+ reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);
+ } else {
+ reqAuthContext.setComparison(config.getAuthnContextComparison());
+ }
+
+ reqAuthContext.getAuthnContextClassRefs().add(authnClassRef);
+ authReq.setRequestedAuthnContext(reqAuthContext);
+ }
+
+ // set request Subject element
+ if (StringUtils.isNotEmpty(config.getSubjectNameID())) {
+ final Subject reqSubject = Saml2Utils.createSamlObject(Subject.class);
+ final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class);
+
+ subjectNameID.setValue(config.getSubjectNameID());
+ if (StringUtils.isNotEmpty(config.getSubjectNameIdQualifier())) {
+ subjectNameID.setNameQualifier(config.getSubjectNameIdQualifier());
+ }
+
+ if (StringUtils.isNotEmpty(config.getSubjectNameIdFormat())) {
+ subjectNameID.setFormat(config.getSubjectNameIdFormat());
+ } else {
+ subjectNameID.setFormat(NameIDType.TRANSIENT);
+ }
+
+ reqSubject.setNameID(subjectNameID);
+
+ if (config.getSubjectConformationDate() != null) {
+ final SubjectConfirmation subjectConformation =
+ Saml2Utils.createSamlObject(SubjectConfirmation.class);
+ final SubjectConfirmationData subjectConformDate =
+ Saml2Utils.createSamlObject(SubjectConfirmationData.class);
+ subjectConformation.setSubjectConfirmationData(subjectConformDate);
+ reqSubject.getSubjectConfirmations().add(subjectConformation);
+
+ if (config.getSubjectConformationMethode() != null) {
+ subjectConformation.setMethod(config.getSubjectConformationMethode());
+ }
+
+ subjectConformDate.setDOM(config.getSubjectConformationDate());
+
+ }
+
+ authReq.setSubject(reqSubject);
+
+ }
+
+ // set ProviderName
+ if (StringUtils.isNotEmpty(config.getProviderName())) {
+ authReq.setProviderName(config.getProviderName());
+ }
+
+ // set RequesterId in case of proxy mode
+ if (StringUtils.isNotEmpty(config.getScopeRequesterId())) {
+ final Scoping scope = Saml2Utils.createSamlObject(Scoping.class);
+ final RequesterID requesterId = Saml2Utils.createSamlObject(RequesterID.class);
+ requesterId.setRequesterID(config.getScopeRequesterId());
+ scope.getRequesterIDs().add(requesterId);
+ authReq.setScoping(scope);
+
+ }
+
+ // add optional requested attributes
+ if (config.getRequestedAttributes() != null) {
+ final List<EaafRequestedAttribute> reqAttr = config.getRequestedAttributes();
+ final Extensions extenstions = new EaafRequestExtensionBuilder().buildObject();
+ final EaafRequestedAttributes reqAttributs =
+ Saml2Utils.createSamlObject(EaafRequestedAttributes.class);
+ reqAttributs.getAttributes().addAll(reqAttr);
+ extenstions.getUnknownXMLObjects().add(reqAttributs);
+ authReq.setExtensions(extenstions);
+
+ }
+
+ // select message encoder
+ IEncoder binding = null;
+ if (endpoint.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
+ binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class);
+
+ } else if (endpoint.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {
+ binding = springContext.getBean("PvpPostBinding", PostBinding.class);
+
+ } else {
+ log.warn("Binding: {} is not supported", endpoint.getBinding());
+ throw new AuthnRequestBuildException("sp.pvp2.00",
+ new Object[] { config.getSpNameForLogging(), idpEntity.getEntityID() });
+
+ }
+
+ // encode message
+ binding.encodeRequest(null, httpResp, authReq, endpoint.getLocation(),
+ pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq);
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java
new file mode 100644
index 00000000..7fbd2daf
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java
@@ -0,0 +1,16 @@
+package at.gv.egiz.eaaf.modules.pvp2.sp.impl.logging;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+public class PvpSpModuleMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/pvp_sp_messages");
+
+ }
+
+}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java
index 22f1cb06..b12a5913 100644
--- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java
@@ -1,29 +1,22 @@
-/*******************************************************************************
- * Copyright 2017 Graz University of Technology
- * EAAF-Core Components has been developed in a cooperation between EGIZ,
- * A-SIT Plus, A-SIT, and Graz University of Technology.
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
*
- * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European
+ * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in
+ * compliance with the Licence. You may obtain a copy of the Licence at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- *
- * This product combines work with different licenses. See the "NOTICE" text
- * file for details on the various modules and licenses.
- * The "NOTICE" text file is part of the distribution. Any derivative works
- * that you distribute must include a readable copy of the "NOTICE" text file.
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
-/*******************************************************************************
- *******************************************************************************/
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence
+ * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the Licence for the specific language governing permissions and limitations under
+ * the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text file for details on the
+ * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative
+ * works that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
package at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils;
import java.util.ArrayList;
@@ -35,308 +28,346 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption;
+
import org.apache.commons.lang3.StringUtils;
-import org.opensaml.saml2.core.Assertion;
-import org.opensaml.saml2.core.Attribute;
-import org.opensaml.saml2.core.AttributeStatement;
-import org.opensaml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml2.core.AuthnStatement;
-import org.opensaml.saml2.core.Response;
-import org.opensaml.saml2.core.StatusResponseType;
-import org.opensaml.saml2.core.Subject;
-import org.opensaml.xml.XMLObject;
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.core.AttributeStatement;
+import org.opensaml.saml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml.saml2.core.AuthnStatement;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.StatusResponseType;
+import org.opensaml.saml.saml2.core.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import at.gv.egiz.eaaf.modules.pvp2.PVPConstants;
-import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption;
-
public class AssertionAttributeExtractor {
-
- private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class);
-
- private Assertion assertion = null;
- private Map<String, List<String>> attributs = new HashMap<String, List<String>>();
- //private PersonalAttributeList storkAttributes = new PersonalAttributeList();
-
- private final List<String> minimalMDSAttributeNamesList = Arrays.asList(
- PVPConstants.PRINCIPAL_NAME_NAME,
- PVPConstants.GIVEN_NAME_NAME,
- PVPConstants.BIRTHDATE_NAME,
- PVPConstants.BPK_NAME);
-
- private final List<String> minimalIDLAttributeNamesList = Arrays.asList(
- PVPConstants.EID_IDENTITY_LINK_NAME,
- PVPConstants.EID_SOURCE_PIN_NAME,
- PVPConstants.EID_SOURCE_PIN_TYPE_NAME);
-
- /**
- * Parse the SAML2 Response element and extracts included information
- * <br><br>
- * <b>INFO:</b> Actually, only the first SAML2 Assertion of the SAML2 Response is used!
- *
- * @param samlResponse SAML2 Response
- * @throws AssertionAttributeExtractorExeption
- */
- public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption {
- if (samlResponse != null && samlResponse instanceof Response) {
- List<Assertion> assertions = ((Response) samlResponse).getAssertions();
- if (assertions.size() == 0)
- throw new AssertionAttributeExtractorExeption("Assertion");
-
- else if (assertions.size() > 1)
- log.warn("Found more then ONE PVP2.1 assertions. Only the First is used.");
-
- assertion = assertions.get(0);
- internalInitialize();
-
- } else
- throw new AssertionAttributeExtractorExeption();
- }
-
- /**
- * Parse the SAML2 Assertion element and extracts included information
- * <br><br>
- *
- * @param assertion SAML2 Assertion
- * @throws AssertionAttributeExtractorExeption
- */
- public AssertionAttributeExtractor(Assertion assertion) throws AssertionAttributeExtractorExeption {
- this.assertion = assertion;
- internalInitialize();
-
- }
-
- /**
- * Get all SAML2 attributes from first SAML2 AttributeStatement element
- *
- * @return List of SAML2 Attributes
- */
- public List<Attribute> getAllResponseAttributesFromFirstAttributeStatement() {
- return assertion.getAttributeStatements().get(0).getAttributes();
-
- }
-
- /**
- * Get all SAML2 attributes of specific SAML2 AttributeStatement element
- *
- * @param attrStatementID List ID of the AttributeStatement element
- * @return List of SAML2 Attributes
- */
- public List<Attribute> getAllResponseAttributes(int attrStatementID) {
- return assertion.getAttributeStatements().get(attrStatementID).getAttributes();
-
- }
-
- /**
- * check attributes from assertion with minimal required attribute list
- * @return
- */
- public boolean containsAllRequiredAttributes() {
- return containsAllRequiredAttributes(minimalMDSAttributeNamesList)
- || containsAllRequiredAttributes(minimalIDLAttributeNamesList);
-
- }
-
- /**
- * check attributes from assertion with attributeNameList
- * bPK or enc_bPK are always needed
- *
- * @param List of attributes which are required
- *
- * @return
- */
- public boolean containsAllRequiredAttributes(Collection<String> attributeNameList) {
-
- //first check if a bPK or an encrypted bPK is available
- boolean flag = true;
- for (String attr : attributeNameList) {
- if (!attributs.containsKey(attr)) {
- flag = false;
- log.debug("Assertion contains no Attribute " + attr);
-
- }
-
- }
-
- if (flag)
- return flag;
-
- else {
- log.debug("Assertion contains no all minimum attributes from: " + attributeNameList.toString());
- return false;
-
- }
- }
-
- public boolean containsAttribute(String attributeName) {
- return attributs.containsKey(attributeName);
-
- }
-
- public String getSingleAttributeValue(String attributeName) {
- if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0)
- return attributs.get(attributeName).get(0);
- else
- return null;
-
- }
-
- public List<String> getAttributeValues(String attributeName) {
- return attributs.get(attributeName);
-
- }
-
- /**
- * Return all include PVP attribute names
- *
- * @return
- */
- public Set<String> getAllIncludeAttributeNames() {
- return attributs.keySet();
-
- }
-
-// public PersonalAttributeList getSTORKAttributes() {
-// return storkAttributes;
-// }
-
-
- public String getNameID() throws AssertionAttributeExtractorExeption {
- if (assertion.getSubject() != null) {
- Subject subject = assertion.getSubject();
-
- if (subject.getNameID() != null) {
- if (StringUtils.isNotEmpty(subject.getNameID().getValue()))
- return subject.getNameID().getValue();
-
- else
- log.error("SAML2 NameID Element is empty.");
- }
- }
-
- throw new AssertionAttributeExtractorExeption("nameID");
- }
-
- /**
- * Get the Id attribute from SAML2 assertion
- *
- * @return
- */
- public String getAssertionID() {
- return assertion.getID();
-
- }
-
- public String getSessionIndex() throws AssertionAttributeExtractorExeption {
- AuthnStatement authn = getAuthnStatement();
-
- if (StringUtils.isNotEmpty(authn.getSessionIndex()))
- return authn.getSessionIndex();
-
- else
- throw new AssertionAttributeExtractorExeption("SessionIndex");
- }
-
- /**
- * @return
- * @throws AssertionAttributeExtractorExeption
- */
- public String getQAALevel() throws AssertionAttributeExtractorExeption {
- AuthnStatement authn = getAuthnStatement();
- if (authn.getAuthnContext() != null && authn.getAuthnContext().getAuthnContextClassRef() != null) {
- AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef();
-
- if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef()))
- return qaaClass.getAuthnContextClassRef();
-
- else
- throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)");
- }
-
- throw new AssertionAttributeExtractorExeption("AuthnContextClassRef");
- }
-
- public Assertion getFullAssertion() {
- return assertion;
- }
-
-
- /**
- * Get the Assertion validTo period
- *
- * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment' element is used.
- * If this is empty, this method returns value of SAML 'Conditions' element.
- *
- * @return Date, until this SAML2 assertion is valid
- */
- public Date getAssertionNotOnOrAfter() {
- if (getFullAssertion().getAuthnStatements() != null
- && getFullAssertion().getAuthnStatements().size() > 0) {
- for (AuthnStatement el : getFullAssertion().getAuthnStatements()) {
- if (el.getSessionNotOnOrAfter() != null)
- return (el.getSessionNotOnOrAfter().toDate());
- }
-
- }
-
- return getFullAssertion().getConditions().getNotOnOrAfter().toDate();
-
- }
-
- /**
- * Get the Assertion validFrom period
- *
- * This method returns value of SAML 'Conditions' element.
- *
- * @return Date, after this SAML2 assertion is valid, otherwise null
- */
- public Date getAssertionNotBefore() {
- try {
- return getFullAssertion().getConditions().getNotBefore().toDate();
-
- } catch (NullPointerException e) {
- return null;
-
- }
-
- }
-
- private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption {
- List<AuthnStatement> authnList = assertion.getAuthnStatements();
- if (authnList.size() == 0)
- throw new AssertionAttributeExtractorExeption("AuthnStatement");
-
- else if (authnList.size() > 1)
- log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used.");
-
- return authnList.get(0);
- }
-
- private void internalInitialize() {
- if (assertion.getAttributeStatements() != null &&
- assertion.getAttributeStatements().size() > 0) {
- AttributeStatement attrStat = assertion.getAttributeStatements().get(0);
- for (Attribute attr : attrStat.getAttributes()) {
- if (attr.getName().startsWith(PVPConstants.STORK_ATTRIBUTE_PREFIX)) {
- List<String> storkAttrValues = new ArrayList<String>();
- for (XMLObject el : attr.getAttributeValues())
- storkAttrValues.add(el.getDOM().getTextContent());
-
-// PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(),
-// false, storkAttrValues , "Available");
-// storkAttributes.put(attr.getName(), storkAttr );
-
- } else {
- List<String> attrList = new ArrayList<String>();
- for (XMLObject el : attr.getAttributeValues())
- attrList.add(el.getDOM().getTextContent());
-
- attributs.put(attr.getName(), attrList);
-
- }
- }
- }
- }
+
+ private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class);
+
+ private Assertion assertion = null;
+ private final Map<String, List<String>> attributs = new HashMap<>();
+ // private PersonalAttributeList storkAttributes = new PersonalAttributeList();
+
+ @Deprecated
+ private final List<String> minimalMdsAttributeNamesList =
+ Arrays.asList(PvpConstants.PRINCIPAL_NAME_NAME, PvpConstants.GIVEN_NAME_NAME,
+ PvpConstants.BIRTHDATE_NAME, PvpConstants.BPK_NAME);
+
+ @Deprecated
+ private final List<String> minimalIdlAttributeNamesList =
+ Arrays.asList(PvpConstants.EID_IDENTITY_LINK_NAME, PvpConstants.EID_SOURCE_PIN_NAME,
+ PvpConstants.EID_SOURCE_PIN_TYPE_NAME);
+
+ private final List<String> minimalEidAttributeNamesList =
+ Arrays.asList(ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME);
+
+ /**
+ * Parse the SAML2 Response element and extracts included information. <br>
+ * <br>
+ * <b>INFO:</b> Actually, only the first SAML2 Assertion of the SAML2 Response
+ * is used!
+ *
+ * @param samlResponse SAML2 Response
+ * @throws AssertionAttributeExtractorExeption In case of an error
+ */
+ public AssertionAttributeExtractor(final StatusResponseType samlResponse)
+ throws AssertionAttributeExtractorExeption {
+ if (samlResponse != null && samlResponse instanceof Response) {
+ final List<Assertion> assertions = ((Response) samlResponse).getAssertions();
+ if (assertions.size() == 0) {
+ throw new AssertionAttributeExtractorExeption("Assertion");
+ } else if (assertions.size() > 1) {
+ log.warn("Found more then ONE PVP2.1 assertions. Only the First is used.");
+ }
+
+ assertion = assertions.get(0);
+ internalInitialize();
+
+ } else {
+ throw new AssertionAttributeExtractorExeption();
+ }
+ }
+
+ /**
+ * Parse the SAML2 Assertion element and extracts included information. <br>
+ * <br>
+ *
+ * @param assertion SAML2 Assertion
+ * @throws AssertionAttributeExtractorExeption In case of an error
+ */
+ public AssertionAttributeExtractor(final Assertion assertion)
+ throws AssertionAttributeExtractorExeption {
+ this.assertion = assertion;
+ internalInitialize();
+
+ }
+
+ /**
+ * Get all SAML2 attributes from first SAML2 AttributeStatement element.
+ *
+ * @return List of SAML2 Attributes
+ */
+ public List<Attribute> getAllResponseAttributesFromFirstAttributeStatement() {
+ return assertion.getAttributeStatements().get(0).getAttributes();
+
+ }
+
+ /**
+ * Get all SAML2 attributes of specific SAML2 AttributeStatement element.
+ *
+ * @param attrStatementID List ID of the AttributeStatement element
+ * @return List of SAML2 Attributes
+ */
+ public List<Attribute> getAllResponseAttributes(final int attrStatementID) {
+ return assertion.getAttributeStatements().get(attrStatementID).getAttributes();
+
+ }
+
+ /**
+ * check attributes from assertion with minimal required attribute list.
+ *
+ * @return
+ */
+ public boolean containsAllRequiredAttributes() {
+ return containsAllRequiredAttributes(minimalEidAttributeNamesList)
+ || containsAllRequiredAttributes(minimalIdlAttributeNamesList)
+ || containsAllRequiredAttributes(minimalMdsAttributeNamesList);
+
+ }
+
+ /**
+ * check attributes from assertion with attributeNameList bPK or enc_bPK are
+ * always needed.
+ *
+ * @param attributeNameList List of attributes which are required
+ *
+ * @return
+ */
+ public boolean containsAllRequiredAttributes(final Collection<String> attributeNameList) {
+
+ // first check if a bPK or an encrypted bPK is available
+ boolean flag = true;
+ for (final String attr : attributeNameList) {
+ if (!attributs.containsKey(attr)) {
+ flag = false;
+ log.debug("Assertion contains no Attribute " + attr);
+
+ }
+
+ }
+
+ if (flag) {
+ return flag;
+ } else {
+ log.debug(
+ "Assertion contains no all minimum attributes from: " + attributeNameList.toString());
+ return false;
+
+ }
+ }
+
+ public boolean containsAttribute(final String attributeName) {
+ return attributs.containsKey(attributeName);
+
+ }
+
+ /**
+ * Get single attribute with name.
+ *
+ * @param attributeName attribute Name
+ * @return Attribute value
+ */
+ public String getSingleAttributeValue(final String attributeName) {
+ if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) {
+ return attributs.get(attributeName).get(0);
+ } else {
+ return null;
+ }
+
+ }
+
+ public List<String> getAttributeValues(final String attributeName) {
+ return attributs.get(attributeName);
+
+ }
+
+ /**
+ * Return all include PVP attribute names.
+ *
+ * @return
+ */
+ public Set<String> getAllIncludeAttributeNames() {
+ return attributs.keySet();
+
+ }
+
+ /**
+ * Get User's nameId.
+ *
+ * @return nameId
+ * @throws AssertionAttributeExtractorExeption In case of an error
+ */
+ public String getNameID() throws AssertionAttributeExtractorExeption {
+ if (assertion.getSubject() != null) {
+ final Subject subject = assertion.getSubject();
+
+ if (subject.getNameID() != null) {
+ if (StringUtils.isNotEmpty(subject.getNameID().getValue())) {
+ return subject.getNameID().getValue();
+ } else {
+ log.error("SAML2 NameID Element is empty.");
+ }
+ }
+ }
+
+ throw new AssertionAttributeExtractorExeption("nameID");
+ }
+
+ /**
+ * Get the Id attribute from SAML2 assertion.
+ *
+ * @return
+ */
+ public String getAssertionID() {
+ return assertion.getID();
+
+ }
+
+ /**
+ * Get SessionIndex from assertion.
+ *
+ * @return sessionIndex
+ * @throws AssertionAttributeExtractorExeption In case of an error
+ */
+ public String getSessionIndex() throws AssertionAttributeExtractorExeption {
+ final AuthnStatement authn = getAuthnStatement();
+
+ if (StringUtils.isNotEmpty(authn.getSessionIndex())) {
+ return authn.getSessionIndex();
+ } else {
+ throw new AssertionAttributeExtractorExeption("SessionIndex");
+ }
+ }
+
+ /**
+ * Get LoA from Assertion.
+ *
+ * @return LoA
+ * @throws AssertionAttributeExtractorExeption In case of an error
+ */
+ public String getQaaLevel() throws AssertionAttributeExtractorExeption {
+ final AuthnStatement authn = getAuthnStatement();
+ if (authn.getAuthnContext() != null
+ && authn.getAuthnContext().getAuthnContextClassRef() != null) {
+ final AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef();
+
+ if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef())) {
+ return qaaClass.getAuthnContextClassRef();
+ } else {
+ throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)");
+ }
+ }
+
+ throw new AssertionAttributeExtractorExeption("AuthnContextClassRef");
+ }
+
+ public Assertion getFullAssertion() {
+ return assertion;
+ }
+
+ /**
+ * Get the Assertion validTo period.
+ *
+ * <p>
+ * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment'
+ * element is used. If this is empty, this method returns value of SAML
+ * 'Conditions' element.
+ * </p>
+ *
+ * @return Date, until this SAML2 assertion is valid
+ */
+ public Date getAssertionNotOnOrAfter() {
+ if (getFullAssertion().getAuthnStatements() != null
+ && getFullAssertion().getAuthnStatements().size() > 0) {
+ for (final AuthnStatement el : getFullAssertion().getAuthnStatements()) {
+ if (el.getSessionNotOnOrAfter() != null) {
+ return el.getSessionNotOnOrAfter().toDate();
+ }
+ }
+
+ }
+
+ return getFullAssertion().getConditions().getNotOnOrAfter().toDate();
+
+ }
+
+ /**
+ * Get the Assertion issuing date.
+ *
+ * <p>
+ * This method returns value of SAML 'Conditions' element.
+ * </p>
+ *
+ * @return Date, when the SAML2 assertion was issued, otherwise null
+ */
+ public Date getAssertionIssuingDate() {
+ try {
+ return getFullAssertion().getIssueInstant().toDate();
+
+ } catch (final NullPointerException e) {
+ return null;
+
+ }
+ }
+
+ /**
+ * Get the Assertion validFrom period.
+ *
+ * <p>
+ * This method returns value of SAML 'Conditions' element.
+ * </p>
+ *
+ * @return Date, after this SAML2 assertion is valid, otherwise null
+ */
+ public Date getAssertionNotBefore() {
+ try {
+ return getFullAssertion().getConditions().getNotBefore().toDate();
+
+ } catch (final NullPointerException e) {
+ return null;
+
+ }
+ }
+
+ private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption {
+ final List<AuthnStatement> authnList = assertion.getAuthnStatements();
+ if (authnList.size() == 0) {
+ throw new AssertionAttributeExtractorExeption("AuthnStatement");
+ } else if (authnList.size() > 1) {
+ log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used.");
+ }
+
+ return authnList.get(0);
+ }
+
+ private void internalInitialize() {
+ if (assertion.getAttributeStatements() != null
+ && assertion.getAttributeStatements().size() > 0) {
+ final AttributeStatement attrStat = assertion.getAttributeStatements().get(0);
+ for (final Attribute attr : attrStat.getAttributes()) {
+ final List<String> attrList = new ArrayList<>();
+ for (final XMLObject el : attr.getAttributeValues()) {
+ attrList.add(el.getDOM().getTextContent());
+ attributs.put(attr.getName(), attrList);
+
+ }
+ }
+ }
+ }
}
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
new file mode 100644
index 00000000..9a6cb2d2
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -0,0 +1 @@
+at.gv.egiz.eaaf.modules.pvp2.sp.Pvp2SProfileSpSpringResourceProvider \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml
new file mode 100644
index 00000000..439ad005
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <bean id="pvpSpLogMessageSource"
+ class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.logging.PvpSpModuleMessageSource" />
+
+ <bean id="pvpAuthnRequestBuilder"
+ class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.PvpAuthnRequestBuilder" />
+
+</beans> \ No newline at end of file
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties
new file mode 100644
index 00000000..682c3f18
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties
@@ -0,0 +1,17 @@
+sp.pvp2.00=Can not build PVP AuthnRequest for {0} {1}. No valid SingleSignOnService endpoint found.
+sp.pvp2.01=Can not build PVP AuthnRequest for {0}. IDP is not allowed for federated authentication.
+sp.pvp2.02=Can not build PVP AuthnRequest for {0}. IDP has no (valid) metadata.
+sp.pvp2.03=Receive PVP Response from {0} with unsupported Binding.
+sp.pvp2.04=Receive invalid PVP Response from {0}. No PVP metadata found.
+sp.pvp2.05=Receive invalid PVP Response from {0} {1}. StatusCode:{2} Msg:{3}.
+sp.pvp2.06=Receive invalid PVP Response from {0}. Assertion does not contain all required attributes.
+sp.pvp2.07=Receive invalid PVP Response from {0}. Attribute {1} is not valid.
+sp.pvp2.08=Receive invalid PVP Response from {0}. Response issuer {1} is not valid or allowed.
+sp.pvp2.09=Receive invalid PVP Response from {0} {1}. StatusCodes:{2} {3} Msg:{4}
+sp.pvp2.10=Receive invalid PVP Response from {0}. No valid assertion included.
+sp.pvp2.11=Receive invalid PVP Response from {0}. Assertion decryption FAILED.
+sp.pvp2.12=Receive invalid PVP Response from {0}. Msg:{1}
+sp.pvp2.13=Can not build PVP AuthnRequest for {0}. Internal processing error.
+
+
+
diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java
new file mode 100644
index 00000000..4a132c3f
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java
@@ -0,0 +1,57 @@
+package at.gv.egiz.eaaf.modules.pvp2.sp.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import at.gv.egiz.eaaf.core.test.TestConstants;
+import at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider;
+import at.gv.egiz.eaaf.modules.pvp2.sp.Pvp2SProfileSpSpringResourceProvider;
+
+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;
+
+
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class Pvp2SProfileSpSpringResourceProviderTest {
+
+ @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",
+ Pvp2SProfileSpSpringResourceProvider.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_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java
new file mode 100644
index 00000000..90bb084a
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java
@@ -0,0 +1,39 @@
+package at.gv.egiz.eaaf.modules.pvp2.sp.test;
+
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/eaaf_pvp_sp.beans.xml"})
+public class PvpSpMessageSourceTest {
+
+ @Autowired
+ private ResourceLoader loader;
+ @Autowired(required = false)
+ private List<IMessageSourceLocation> messageSources;
+
+ @Test
+ public void checkMessageSources() {
+ Assert.assertNotNull("No messageSource", messageSources);
+
+ for (final IMessageSourceLocation messageSource : messageSources) {
+ Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation());
+
+ for (final String el : messageSource.getMessageSourceLocation()) {
+ final Resource messages = loader.getResource(el + ".properties");
+ Assert.assertTrue("Source not exist", messages.exists());
+
+ }
+ }
+ }
+}
diff --git a/eaaf_modules/pom.xml b/eaaf_modules/pom.xml
index b1b5bf91..228a41cf 100644
--- a/eaaf_modules/pom.xml
+++ b/eaaf_modules/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>at.gv.egiz</groupId>
<artifactId>eaaf</artifactId>
- <version>1.0.13.2</version>
+ <version>1.1.0</version>
</parent>
<groupId>at.gv.egiz.eaaf</groupId>