aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/authmodule-eIDAS-v2/checks/spotbugs-exclude.xml44
-rw-r--r--modules/authmodule-eIDAS-v2/pom.xml295
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java192
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationModulImpl.java87
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationSpringResourceProvider.java52
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasSignalServlet.java161
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java115
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidPostProcessingException.java40
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasAttributeException.java34
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasSAuthenticationException.java41
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasValidationException.java34
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SqliteServiceException.java40
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SzrCommunicationException.java38
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java425
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeEidProcessor.java113
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/GenericEidProcessor.java61
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/INationalEidProcessor.java81
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/LuEidProcessor.java61
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/NlEidProcessor.java54
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java211
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/CcSpecificEidProcessingService.java135
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasAttributeRegistry.java180
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasDataStore.java363
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/ICcSpecificEidProcessingService.java61
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java522
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrService.java164
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java503
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java255
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java130
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java179
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java305
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/LoggingHandler.java72
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/validator/EidasResponseValidator.java175
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider1
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml29
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/additional-attributes.xml42
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/eidas-attributes.xml379
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml100
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml122
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.1.WSDL939
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.WSDL901
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl441
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp1.xsd133
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd133
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr.xsd388
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd30
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd54
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd10
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml54
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml10
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd443
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd31
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/resources/templates/eidas_node_forward.html36
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthSpringResourceProviderTest.java56
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthenticationModulImplTest.java121
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasDataStoreTest.java118
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasSignalServletTest.java244
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java439
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java236
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/dummy/DummySpecificCommunicationService.java66
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java491
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java464
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java637
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveEidasResponseTaskTest.java223
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/JoseUtilsTest.java139
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasAttributePostProcessingTest.java460
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java193
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingSecondTest.java157
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasResponseValidatorTest.java333
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_mapConfig.xml20
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_realConfig.xml25
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_test.xml73
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml67
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/additional-attributes.xml39
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/eidas-attributes.xml376
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties117
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties114
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties118
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_4.properties114
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties116
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/data/junit.jksbin0 -> 5738 bytes
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/data/szr/signed_eidasBind.jws1
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_error_travelerdocexists.xml6
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_1.xml50
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_2.xml50
-rw-r--r--modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jksbin0 -> 2028 bytes
-rw-r--r--modules/authmodule_id-austria/checks/spotbugs-exclude.xml29
-rw-r--r--modules/authmodule_id-austria/pom.xml171
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java123
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthenticationSpringResourceProvider.java56
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaEidasProxyAuthenticationModulImpl.java91
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/EidasConnecorUniqueIdAttributeBuilder.java52
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMessageSource.java22
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMetadataConfiguration.java462
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthRequestBuilderConfiguration.java307
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthMetadataController.java150
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthSignalController.java94
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java393
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java205
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthCredentialProvider.java130
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthMetadataProvider.java168
-rw-r--r--modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/Utils.java44
-rw-r--r--modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider1
-rw-r--r--modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder1
-rw-r--r--modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties10
-rw-r--r--modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml18
-rw-r--r--modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml36
-rw-r--r--modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml23
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaAuthSpringResourceProviderTest.java56
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaEidasProxyAuthenticationModulImplTest.java102
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/EidasConnecorUniqueIdAttributeBuilderTest.java54
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/config/IdAustriaAuthMessageSourceTest.java50
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java186
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthSignalControllerTest.java200
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java792
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java455
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java413
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java236
-rw-r--r--modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderSecondTest.java65
-rw-r--r--modules/authmodule_id-austria/src/test/resources/config/junit.jksbin0 -> 3980 bytes
-rw-r--r--modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties44
-rw-r--r--modules/authmodule_id-austria/src/test/resources/config/junit_test.jksbin0 -> 8410 bytes
-rw-r--r--modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jksbin0 -> 4818 bytes
-rw-r--r--modules/authmodule_id-austria/src/test/resources/config/pvp.jksbin0 -> 4833 bytes
-rw-r--r--modules/authmodule_id-austria/src/test/resources/config/pvp.p12bin0 -> 5494 bytes
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml49
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml49
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml43
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.xml52
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_jur.xml63
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_nat.xml66
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml46
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml52
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml52
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml46
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml46
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml46
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml45
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt21
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml146
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml46
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml46
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml84
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml74
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt11
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt18
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt27
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/pvp_postbinding_template.html3
-rw-r--r--modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml66
-rw-r--r--modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml20
-rw-r--r--modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml32
-rw-r--r--modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml24
-rw-r--r--modules/core_common_lib/checks/spotbugs-exclude.xml20
-rw-r--r--modules/core_common_lib/pom.xml106
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsConnectorEventCodes.java52
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java229
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/BasicConfigurationProvider.java155
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java171
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/SpringBootBasicConfigurationProvider.java122
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java77
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java69
-rw-r--r--modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java148
-rw-r--r--modules/core_common_lib/src/main/resources/common_gui.beans.xml60
-rw-r--r--modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/BasicConfigProviderTest.java156
-rw-r--r--modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/ServiceProviderConfigurationTest.java54
-rw-r--r--modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/SpringBootBasicConfigurationProviderTest.java148
-rw-r--r--modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummyConfigMap.java120
-rw-r--r--modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummySpConfiguration.java28
-rw-r--r--modules/core_common_lib/src/test/resources/SpringTest-context_basic_realConfig.xml25
-rw-r--r--modules/core_common_lib/src/test/resources/config/junit_config_1.properties124
-rw-r--r--modules/core_common_webapp/checks/spotbugs-exclude.xml12
-rw-r--r--modules/core_common_webapp/pom.xml136
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java170
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java60
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java255
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java220
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java69
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java52
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java90
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java110
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java141
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java60
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java182
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java35
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java180
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java169
-rw-r--r--modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java70
-rw-r--r--modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml61
-rw-r--r--modules/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml39
-rw-r--r--modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java70
-rw-r--r--modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java102
-rw-r--r--modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java635
-rw-r--r--modules/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties113
-rw-r--r--modules/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties113
-rw-r--r--modules/core_common_webapp/src/test/resources/config/junit_config_3.properties148
-rw-r--r--modules/core_common_webapp/src/test/resources/config/log4j.properties54
-rw-r--r--modules/core_common_webapp/src/test/resources/data/metadata_valid.xml106
-rw-r--r--modules/core_common_webapp/src/test/resources/data/test_idl_1.xml46
-rw-r--r--modules/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml22
-rw-r--r--modules/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml22
-rw-r--r--modules/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml15
-rw-r--r--modules/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml70
-rw-r--r--modules/core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml25
-rw-r--r--modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml20
-rw-r--r--modules/eidas_proxy-sevice/pom.xml184
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java22
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java54
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java52
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java19
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java443
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java374
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java28
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java45
-rw-r--r--modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider1
-rw-r--r--modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties14
-rw-r--r--modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml28
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java50
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java56
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java666
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java637
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml39
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml376
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties6
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml20
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml42
-rw-r--r--modules/pom.xml23
226 files changed, 30389 insertions, 0 deletions
diff --git a/modules/authmodule-eIDAS-v2/checks/spotbugs-exclude.xml b/modules/authmodule-eIDAS-v2/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..d961b4d6
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/checks/spotbugs-exclude.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+ <Match>
+ <!-- Do not check code generated by Apache CXF framework -->
+ <Class name="~szrservices.*"/>
+ <Class name="~at.gv.e_government.reference.namespace.persondata.*" />
+ <Class name="~org.w3._2000._09.xmldsig.*" />
+ </Match>
+ <Match>
+ <!-- Logging of SAML2 responses in case of errors or for debugging is allowed -->
+ <Class name="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet" />
+ <Method name="getPendingRequestId" />
+ <Bug pattern="CRLF_INJECTION_LOGS" />
+ </Match>
+ <Match>
+ <!-- CSFR protection is implemented by pendingRequestId that is an one-time token -->
+ <Class name="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet" />
+ <Method name="restoreEidasAuthProcess" />
+ <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" />
+ </Match>
+ <Match>
+ <!-- File path is only loaded from configuration -->
+ <Class name="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry" />
+ <Method name="initialize" />
+ <Bug pattern="PATH_TRAVERSAL_IN" />
+ </Match>
+ <Match>
+ <!-- Redirect URL is only loaded from configuration -->
+ <Class name="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateAuthnRequestTask" />
+ <Method name="execute" />
+ <Bug pattern="UNVALIDATED_REDIRECT" />
+ </Match>
+ <Match>
+ <!-- Builder pattern does not expose date elements -->
+ <OR>
+ <Class name="at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData" />
+ <Class name="at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils$JwsResult"/>
+ </OR>
+ <OR>
+ <Bug pattern="EI_EXPOSE_REP" />
+ <Bug pattern="EI_EXPOSE_REP2" />
+ </OR>
+ </Match>
+</FindBugsFilter>
diff --git a/modules/authmodule-eIDAS-v2/pom.xml b/modules/authmodule-eIDAS-v2/pom.xml
new file mode 100644
index 00000000..f16edb2d
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/pom.xml
@@ -0,0 +1,295 @@
+<?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.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>authmodule-eIDAS-v2</artifactId>
+ <name>eIDAS v2 authentication module</name>
+ <description>eIDAS module based on eIDAS node reference implementation v2.x</description>
+
+ <profiles>
+ <profile>
+ <id>default</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <repositories>
+ <repository>
+ <id>egiz-commons</id>
+ <url>https://apps.egiz.gv.at/maven/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </repository>
+ <repository>
+ <id>eIDASNode-local</id>
+ <name>local</name>
+ <url>file:${basedir}/../../repository</url>
+ </repository>
+ </repositories>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz.components</groupId>
+ <artifactId>egiz-spring-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ </dependency>
+
+ <!-- eIDAS reference implemenation libs -->
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-commons</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <groupId>org.slf4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-light-commons</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-specific-communication-definition</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-jcache-ignite-specific-communication</artifactId>
+ </dependency>
+
+ <!-- other third party libs -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxws</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-jsr310</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.bitbucket.b_c</groupId>
+ <artifactId>jose4j</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.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </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.github.skjolber</groupId>
+ <artifactId>mockito-soap-cxf</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>target/generated-sources/cxf</directory>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-codegen-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ <version>2.2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-xjc</artifactId>
+ <version>2.2.5</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
+ <wsdlOptions>
+ <wsdlOption>
+ <wsdl>${basedir}/src/main/resources/szr_client/SZR_v4.0.wsdl</wsdl>
+ <extraargs>
+ <extraarg>-verbose </extraarg>
+ </extraargs>
+ </wsdlOption>
+ </wsdlOptions>
+ </configuration>
+ <goals>
+ <goal>wsdl2java</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs-maven-plugin</artifactId>
+ <version>${spotbugs-maven-plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>post-unit-check</id>
+ <phase>test</phase>
+ <goals>
+ <goal>check</goal>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <haltOnFailure>true</haltOnFailure>
+ <excludes>
+ <exclude>**/at/gv/e_government/reference/namespace/persondata/_20020228/*</exclude>
+ <exclude>**/org/w3/_2000/_09/*</exclude>
+ <exclude>**/org/w3/_2001/_04/*</exclude>
+ <exclude>**/szrservices/*</exclude>
+ <exclude>**/generated/cxf/*</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- enable co-existence of testng and junit -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <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/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java
new file mode 100644
index 00000000..a554bf57
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java
@@ -0,0 +1,192 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+
+public class Constants {
+
+ public static final String DATA_REQUESTERID = "req_requesterId";
+ public static final String DATA_PROVIDERNAME = "req_providerName";
+ public static final String DATA_REQUESTED_LOA_LIST = "req_requestedLoA";
+ public static final String DATA_REQUESTED_LOA_COMPERISON = "req_requestedLoAComperision";
+ public static final String DATA_FULL_EIDAS_RESPONSE = "resp_fulleIDASResponse";
+
+ // templates for post-binding forwarding
+ public static final String TEMPLATE_POST_FORWARD_NAME = "eidas_node_forward.html";
+ public static final String TEMPLATE_POST_FORWARD_ENDPOINT = "endPoint";
+ public static final String TEMPLATE_POST_FORWARD_TOKEN_NAME = "tokenName";
+ public static final String TEMPLATE_POST_FORWARD_TOKEN_VALUE = "tokenValue";
+
+ // configuration properties
+ public static final String CONIG_PROPS_EIDAS_PREFIX = "auth.eIDAS";
+ public static final String CONIG_PROPS_EIDAS_IS_TEST_IDENTITY = CONIG_PROPS_EIDAS_PREFIX
+ + ".eid.testidentity.default";
+ public static final String CONIG_PROPS_EIDAS_NODE = CONIG_PROPS_EIDAS_PREFIX + ".node_v2";
+ public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode";
+ public static final String CONIG_PROPS_EIDAS_NODE_PUBLICSECTOR_TARGETS = CONIG_PROPS_EIDAS_NODE
+ + ".publicSectorTargets";
+ public static final String CONIG_PROPS_EIDAS_NODE_ENTITYID = CONIG_PROPS_EIDAS_NODE + ".entityId";
+ public static final String CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL = CONIG_PROPS_EIDAS_NODE
+ + ".forward.endpoint";
+
+ public static final String CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD = CONIG_PROPS_EIDAS_NODE
+ + ".forward.method";
+ public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_DEFAULT_ONLYNATURAL =
+ CONIG_PROPS_EIDAS_NODE + ".attributes.requested.onlynatural";
+ public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_CC_SPECIFIC_ONLYNATURAL =
+ CONIG_PROPS_EIDAS_NODE + ".attributes.requested.{0}.onlynatural";
+ public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_REPRESENTATION =
+ CONIG_PROPS_EIDAS_NODE + ".attributes.requested.representation";
+
+ public static final String CONIG_PROPS_EIDAS_NODE_REQUESTERID_USE_HASHED_VERSION =
+ CONIG_PROPS_EIDAS_NODE + ".requesterId.useHashedForm";
+ public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_USE_STATIC_REQUESTERID_FOR_LUX =
+ CONIG_PROPS_EIDAS_NODE + ".requesterId.lu.useStaticRequesterForAll";
+
+ public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME =
+ CONIG_PROPS_EIDAS_NODE + ".workarounds.addAlwaysProviderName";
+ public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER =
+ CONIG_PROPS_EIDAS_NODE + ".workarounds.useRequestIdAsTransactionIdentifier";
+
+ public static final String CONFIG_PROP_EIDAS_NODE_NAMEIDFORMAT =
+ CONIG_PROPS_EIDAS_NODE + ".requested.nameIdFormat";
+
+ public static final String CONIG_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP = CONIG_PROPS_EIDAS_NODE
+ + ".staticProviderNameForPublicSPs";
+ public static final String DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP = "Austria";
+
+ public static final String FORWARD_METHOD_POST = "POST";
+ public static final String FORWARD_METHOD_GET = "GET";
+
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".szrclient";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".useTestService";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_TRACEMESSAGES = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".debug.logfullmessages";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".debug.useDummySolution";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SET_MDS_TO_EIDASBIND = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".eidasbind.mds.inject";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_CONNECTION = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".timeout.connection";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_RESPONSE = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".timeout.response";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_PROD = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".endpoint.prod";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_TEST = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".endpoint.test";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PATH = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".ssl.keyStore.path";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PASSWORD = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".ssl.keyStore.password";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PATH = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".ssl.trustStore.path";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PASSWORD = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".ssl.trustStore.password";
+
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".params.documenttype";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".params.vkz";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_DATE = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".params.issuingdate";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_AUTHORITY =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".params.issuingauthority";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_KEYS_USEDUMMY = CONIG_PROPS_EIDAS_SZRCLIENT
+ + ".params.usedummykeys";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USESRZFORBPKGENERATION =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".params.useSZRForbPKCalculation";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETPLACEOFBIRTHIFAVAILABLE =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".params.setPlaceOfBirthIfAvailable";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETBIRTHNAMEIFAVAILABLE =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".params.setBirthNameIfAvailable";
+
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_REVISIONLOGDATASTORE_ACTIVE =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".revisionlog.eidmapping.active";
+
+ public static final String DEFAULT_MS_NODE_COUNTRY_CODE = "AT";
+
+ @Deprecated
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_SQLLITEDATASTORE_URL =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".workarounds.datastore.sqlite.url";
+ @Deprecated
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_SQLLITEDATASTORE_ACTIVE =
+ CONIG_PROPS_EIDAS_SZRCLIENT + ".workarounds.datastore.sqlite.active";
+
+ // http endpoint descriptions
+ public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/light/sp/post";
+ public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/light/sp/redirect";
+ public static final String eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST = "/eidas/light/ColleagueRequest";
+ public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/light/metadata";
+
+ // eIDAS request parameters
+ public static final String eIDAS_REQ_NAMEID_FORMAT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent";
+
+ // eIDAS attribute names
+ public static final String eIDAS_ATTR_PERSONALIDENTIFIER = "PersonIdentifier";
+ public static final String eIDAS_ATTR_DATEOFBIRTH = "DateOfBirth";
+ public static final String eIDAS_ATTR_CURRENTGIVENNAME = "FirstName";
+ public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "FamilyName";
+ public static final String eIDAS_ATTR_PLACEOFBIRTH = "PlaceOfBirth";
+ public static final String eIDAS_ATTR_BIRTHNAME = "BirthName";
+ public static final String eIDAS_ATTR_CURRENTADDRESS = "CurrentAddress";
+
+ public static final String eIDAS_ATTR_LEGALPERSONIDENTIFIER = "LegalPersonIdentifier";
+ public static final String eIDAS_ATTR_LEGALNAME = "LegalName";
+
+ public static final String eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER = "RepresentativePersonIdentifier";
+ public static final String eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH = "RepresentativeDateOfBirth";
+ public static final String eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME = "RepresentativeFirstName";
+ public static final String eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME = "RepresentativeFamilyName";
+
+
+ public static final String eIDAS_REQ_PARAM_SECTOR_PUBLIC = "public";
+ public static final String eIDAS_REQ_PARAM_SECTOR_PRIVATE = "private";
+
+ public static final String POLICY_DEFAULT_ALLOWED_TARGETS =
+ EaafConstants.URN_PREFIX_CDID.replaceAll("\\.", "\\\\.").replaceAll("\\+", "\\\\+") + ".*";
+
+ // SAML2 Constants
+ public static final String SUCCESS_URI = "urn:oasis:names:tc:SAML:2.0:status:Success";
+ public static final String ERROR_URI = "urn:oasis:names:tc:SAML:2.0:status:Responder";
+
+ public static final String HTTP_CLIENT_DEFAULT_TIMEOUT_CONNECTION = "30"; // seconds
+ public static final String HTTP_CLIENT_DEFAULT_TIMEOUT_RESPONSE = "60"; // seconds
+
+ public static final String SZR_SCHEMA_LOCATIONS =
+ "urn:SZRServices" + " " + "/szr_client/szr.xsd";
+
+ // Default values for SZR communication
+ public static final String SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE = "ELEKTR_DOKUMENT";
+
+ // TODO remove!!!
+ public static final String SZR_CONSTANTS_DEFAULT_ISSUING_DATE = "2014-01-01";
+ public static final String SZR_CONSTANTS_DEFAULT_ISSUING_AUTHORITY = "ms-specific eIDAS-Node for AT";
+ public static final String SZR_CONSTANTS_DEFAULT_PUBKEY_EXPONENT = "AQAB";
+ public static final String SZR_CONSTANTS_DEFAULT_PUBKEY_MODULUS =
+ "AJZyj/+sdCMDRq9RkvbFcgSTVn/OfS8EUE81ddwP8MNuJ1kd1SWBUJPaQX2JLJHrL54mkOhrkhH2M/zcuOTu8nW9TOEg"
+ + "XGjrRB/0HpiYKpV+VDJViyyc/GacNLxN4Anw4pima6gHYaJIw9hQkL/nuO2hyh8PGJd7rxeFXJmbLy+X";
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationModulImpl.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationModulImpl.java
new file mode 100644
index 00000000..85f0873e
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationModulImpl.java
@@ -0,0 +1,87 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+
+/**
+ * eIDAS authentication-process selector.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasAuthenticationModulImpl implements AuthModule {
+
+ private int priority = 1;
+
+ @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;
+ }
+
+ /*
+ * (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) {
+ Serializable flagObj = context.get(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY);
+ if (flagObj != null && flagObj instanceof String
+ && StringUtils.isNotBlank((String) context.get(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY))) {
+ return "eIDASAuthentication_v2";
+ } else {
+ return null;
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()
+ */
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:eIDAS.Authentication.process.xml" };
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationSpringResourceProvider.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationSpringResourceProvider.java
new file mode 100644
index 00000000..535e4f97
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasAuthenticationSpringResourceProvider.java
@@ -0,0 +1,52 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+public class EidasAuthenticationSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "Auth. module for eIDAS Ref. Impl. v2.x";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource eidasAuthConfig = new ClassPathResource("/eidas_v2_auth.beans.xml",
+ EidasAuthenticationSpringResourceProvider.class);
+
+ return new Resource[] { eidasAuthConfig };
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasSignalServlet.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasSignalServlet.java
new file mode 100644
index 00000000..d3cac80c
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/EidasSignalServlet.java
@@ -0,0 +1,161 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractProcessEngineSignalController;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+
+/**
+ * Controler implementation for eIDAS Node communication.
+ *
+ * @author tlenz
+ *
+ */
+@Controller
+public class EidasSignalServlet extends AbstractProcessEngineSignalController {
+
+ private static final Logger log = LoggerFactory.getLogger(EidasSignalServlet.class);
+ @Autowired
+ private ApplicationContext context;
+ @Autowired
+ private EidasAttributeRegistry attrRegistry;
+
+ /**
+ * eIDAS Node communication end-point implementation.
+ *
+ */
+ public EidasSignalServlet() {
+ super();
+ log.debug("Registering servlet {} with mappings '{}' and '{}'.",
+ getClass().getName(), Constants.eIDAS_HTTP_ENDPOINT_SP_POST,
+ Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT);
+
+ }
+
+ @RequestMapping(value = {
+ Constants.eIDAS_HTTP_ENDPOINT_SP_POST,
+ Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT
+ },
+ method = { RequestMethod.POST, RequestMethod.GET })
+ public void restoreEidasAuthProcess(HttpServletRequest req, HttpServletResponse resp) throws IOException,
+ EaafException {
+ signalProcessManagement(req, resp);
+ }
+
+ /**
+ * Protocol specific implementation to get the pending-requestID from http
+ * request object.
+ *
+ * @param request The http Servlet-Request object
+ * @return The Pending-request id
+ *
+ */
+ @Override
+ public String getPendingRequestId(HttpServletRequest request) {
+ // String sessionId = super.getPendingRequestId(request);
+
+ try {
+ // get token from Request
+ final String tokenBase64 = request.getParameter(EidasParameterKeys.TOKEN.toString());
+ if (StringUtils.isEmpty(tokenBase64)) {
+ log.warn("NO eIDAS message token found.");
+ throw new EidasSAuthenticationException("eidas.04", null);
+
+ }
+ log.trace("Receive eIDAS-node token: " + tokenBase64 + " Starting transaction-restore process ... ");
+
+ final SpecificCommunicationService specificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString());
+ final ILightResponse eidasResponse = specificConnectorCommunicationService.getAndRemoveResponse(
+ tokenBase64,
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ String pendingReqId = null;
+ if (StringUtils.isEmpty(eidasResponse.getRelayState())) {
+ log.debug("eIDAS Node returns no RelayState. ");
+
+ if (authConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER,
+ false)) {
+ log.trace("Use lightRequestId to recover session ... ");
+ pendingReqId = transactionStorage.get(eidasResponse.getInResponseToId(), String.class);
+ if (StringUtils.isNotEmpty(pendingReqId)) {
+ log.debug("Restoring session with lightRequestId ... ");
+ transactionStorage.remove(eidasResponse.getInResponseToId());
+
+ }
+ }
+
+ } else {
+ log.debug("Find transaction identifier in SAML2 'RelayState': " + eidasResponse.getRelayState());
+ pendingReqId = eidasResponse.getRelayState();
+
+ }
+
+ if (StringUtils.isNotEmpty(pendingReqId)) {
+ request.setAttribute(Constants.DATA_FULL_EIDAS_RESPONSE, eidasResponse);
+ return pendingReqId;
+
+ }
+
+ log.info("NO transaction identifier found! Stopping process ....");
+ log.trace("FullResponse: " + eidasResponse.toString());
+
+ } catch (final SpecificCommunicationException e) {
+ log.warn("Can NOT load eIDAS Response from cache.", e);
+ log.debug("eIDAS response token was: " + request.getParameter(EidasParameterKeys.TOKEN.toString()));
+
+ } catch (final Exception e) {
+ log.warn("Unable to retrieve moa session id.", e);
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java
new file mode 100644
index 00000000..6c7eeb6b
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java
@@ -0,0 +1,115 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.dao;
+
+import java.text.SimpleDateFormat;
+
+import org.joda.time.DateTime;
+
+import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
+
+public class ErnbEidData {
+
+ private String citizenCountryCode = null;
+
+ // MDS
+ private String pseudonym = null;
+ private String givenName = null;
+ private String familyName = null;
+ private DateTime dateOfBirth = null;
+
+ // additional attributes
+ private String placeOfBirth = null;
+ private String birthName = null;
+ private PostalAddressType address = null;
+
+ public String getCitizenCountryCode() {
+ return citizenCountryCode;
+ }
+
+ public void setCitizenCountryCode(String citizenCountryCode) {
+ this.citizenCountryCode = citizenCountryCode;
+ }
+
+ public String getPseudonym() {
+ return pseudonym;
+ }
+
+ public void setPseudonym(String pseudonym) {
+ this.pseudonym = pseudonym;
+ }
+
+ public String getGivenName() {
+ return givenName;
+ }
+
+ public void setGivenName(String givenName) {
+ this.givenName = givenName;
+ }
+
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ public void setFamilyName(String familyName) {
+ this.familyName = familyName;
+ }
+
+ public DateTime getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+ public void setDateOfBirth(DateTime dateOfBirth) {
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ public String getPlaceOfBirth() {
+ return placeOfBirth;
+ }
+
+ public void setPlaceOfBirth(String placeOfBirth) {
+ this.placeOfBirth = placeOfBirth;
+ }
+
+ public String getBirthName() {
+ return birthName;
+ }
+
+ public void setBirthName(String birthName) {
+ this.birthName = birthName;
+ }
+
+ public PostalAddressType getAddress() {
+ return address;
+ }
+
+ public void setAddress(PostalAddressType address) {
+ this.address = address;
+ }
+
+ public String getFormatedDateOfBirth() {
+ return new SimpleDateFormat("yyyy-MM-dd").format(dateOfBirth.toDate());
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidPostProcessingException.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidPostProcessingException.java
new file mode 100644
index 00000000..f4c0be67
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidPostProcessingException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.exception;
+
+public class EidPostProcessingException extends EidasSAuthenticationException {
+
+ private static final long serialVersionUID = 6780652273831172456L;
+
+ public EidPostProcessingException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+
+ }
+
+ public EidPostProcessingException(String internalMsgId, Object[] params, Throwable e) {
+ super(internalMsgId, params, e);
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasAttributeException.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasAttributeException.java
new file mode 100644
index 00000000..49736d58
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasAttributeException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.exception;
+
+public class EidasAttributeException extends EidasSAuthenticationException {
+ private static final long serialVersionUID = 1L;
+
+ public EidasAttributeException(String attrbuteName) {
+ super("eidas.00", new Object[] { attrbuteName });
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasSAuthenticationException.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasSAuthenticationException.java
new file mode 100644
index 00000000..8ff218e3
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasSAuthenticationException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.exception;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+
+public class EidasSAuthenticationException extends EaafAuthenticationException {
+
+
+ private static final long serialVersionUID = 1L;
+
+ public EidasSAuthenticationException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+ }
+
+ public EidasSAuthenticationException(String internalMsgId, Object[] params, Throwable e) {
+ super(internalMsgId, params, e);
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasValidationException.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasValidationException.java
new file mode 100644
index 00000000..2988dd6f
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/EidasValidationException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.exception;
+
+public class EidasValidationException extends EidasSAuthenticationException {
+
+ private static final long serialVersionUID = 1L;
+
+ public EidasValidationException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SqliteServiceException.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SqliteServiceException.java
new file mode 100644
index 00000000..d48abec9
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SqliteServiceException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.exception;
+
+public class SqliteServiceException extends EidasSAuthenticationException {
+
+ private static final long serialVersionUID = 2278259367925102676L;
+
+ public SqliteServiceException(String internalMsgId, Object[] params, Throwable e) {
+ super(internalMsgId, params, e);
+
+ }
+
+ public SqliteServiceException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SzrCommunicationException.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SzrCommunicationException.java
new file mode 100644
index 00000000..c736cadb
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/SzrCommunicationException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.exception;
+
+public class SzrCommunicationException extends EidasSAuthenticationException {
+
+ private static final long serialVersionUID = 1L;
+
+ public SzrCommunicationException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+ }
+
+ public SzrCommunicationException(String internalMsgId, Object[] params, Throwable e) {
+ super(internalMsgId, params, e);
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java
new file mode 100644
index 00000000..4a3218e9
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java
@@ -0,0 +1,425 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.NonNull;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
+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.IConfigurationWithSP;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+import eu.eidas.auth.commons.protocol.eidas.SpType;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+
+public abstract class AbstractEidProcessor implements INationalEidProcessor {
+ private static final Logger log = LoggerFactory.getLogger(AbstractEidProcessor.class);
+
+ @Autowired
+ protected EidasAttributeRegistry attrRegistry;
+ @Autowired
+ protected IConfigurationWithSP basicConfig;
+
+ @Override
+ public final void preProcess(IRequest pendingReq, Builder authnRequestBuilder) {
+
+ buildLevelOfAssurance(pendingReq.getServiceProviderConfiguration(), authnRequestBuilder);
+ buildProviderNameAndRequesterIdAttribute(pendingReq, authnRequestBuilder);
+ buildRequestedAttributes(authnRequestBuilder);
+
+ }
+
+
+ @Override
+ public final ErnbEidData postProcess(Map<String, Object> eidasAttrMap) throws EidPostProcessingException,
+ EidasAttributeException {
+ final ErnbEidData result = new ErnbEidData();
+
+ final Object eIdentifierObj = eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier((String) eIdentifierObj);
+ result.setCitizenCountryCode(eIdentifier.getFirst());
+
+ // MDS attributes
+ result.setPseudonym(processPseudonym(eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)));
+ result.setFamilyName(processFamilyName(eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME)));
+ result.setGivenName(processGivenName(eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME)));
+ result.setDateOfBirth(processDateOfBirth(eidasAttrMap.get(Constants.eIDAS_ATTR_DATEOFBIRTH)));
+
+ // additional attributes
+ result.setPlaceOfBirth(processPlaceOfBirth(eidasAttrMap.get(Constants.eIDAS_ATTR_PLACEOFBIRTH)));
+ result.setBirthName(processBirthName(eidasAttrMap.get(Constants.eIDAS_ATTR_BIRTHNAME)));
+ result.setAddress(processAddress(eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTADDRESS)));
+
+ return result;
+
+ }
+
+
+ /**
+ * Get a Map of country-specific requested attributes.
+ *
+ * @return
+ */
+ @NonNull
+ protected abstract Map<String, Boolean> getCountrySpecificRequestedAttributes();
+
+ /**
+ * Post-Process the eIDAS CurrentAddress attribute.
+ *
+ * @param currentAddressObj eIDAS current address information
+ * @return current address or null if no attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ * @throws EidasAttributeException if eIDAS attribute is of a wrong type
+ */
+ protected PostalAddressType processAddress(Object currentAddressObj) throws EidPostProcessingException,
+ EidasAttributeException {
+
+ if (currentAddressObj != null) {
+ if (currentAddressObj instanceof PostalAddress) {
+ final PostalAddressType result = new PostalAddressType();
+ result.setPostalCode(((PostalAddress) currentAddressObj).getPostCode());
+ result.setMunicipality(((PostalAddress) currentAddressObj).getPostName());
+
+ // TODO: add more mappings
+
+ return result;
+
+ } else {
+ log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_CURRENTADDRESS + " is of WRONG type");
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTADDRESS);
+
+ }
+
+ } else {
+ log.debug("NO '" + Constants.eIDAS_ATTR_CURRENTADDRESS + "' attribute. Post-Processing skipped ... ");
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Post-Process the eIDAS BirthName attribute.
+ *
+ * @param birthNameObj eIDAS birthname information
+ * @return birthName or null if no attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ * @throws EidasAttributeException if eIDAS attribute is of a wrong type
+ */
+ protected String processBirthName(Object birthNameObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (birthNameObj != null) {
+ if (birthNameObj instanceof String) {
+ return (String) birthNameObj;
+
+ } else {
+ log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_BIRTHNAME + " is of WRONG type");
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_BIRTHNAME);
+
+ }
+
+ } else {
+ log.debug("NO '" + Constants.eIDAS_ATTR_BIRTHNAME + "' attribute. Post-Processing skipped ... ");
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Post-Process the eIDAS PlaceOfBirth attribute.
+ *
+ * @param placeOfBirthObj eIDAS Place-of-Birth information
+ * @return place of Birth or null if no attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ * @throws EidasAttributeException if eIDAS attribute is of a wrong type
+ */
+ protected String processPlaceOfBirth(Object placeOfBirthObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (placeOfBirthObj != null) {
+ if (placeOfBirthObj instanceof String) {
+ return (String) placeOfBirthObj;
+
+ } else {
+ log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_PLACEOFBIRTH + " is of WRONG type");
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_PLACEOFBIRTH);
+
+ }
+
+ } else {
+ log.debug("NO '" + Constants.eIDAS_ATTR_PLACEOFBIRTH + "' attribute. Post-Processing skipped ... ");
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Post-Process the eIDAS DateOfBirth attribute.
+ *
+ * @param dateOfBirthObj eIDAS date-of-birth attribute information
+ * @return formated user's date-of-birth
+ * @throws EidasAttributeException if NO attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ */
+ protected DateTime processDateOfBirth(Object dateOfBirthObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
+ }
+
+ return (DateTime) dateOfBirthObj;
+
+ }
+
+ /**
+ * Post-Process the eIDAS GivenName attribute.
+ *
+ * @param givenNameObj eIDAS givenName attribute information
+ * @return formated user's givenname
+ * @throws EidasAttributeException if NO attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ */
+ protected String processGivenName(Object givenNameObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (givenNameObj == null || !(givenNameObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
+ }
+
+ return (String) givenNameObj;
+
+ }
+
+ /**
+ * Post-Process the eIDAS FamilyName attribute.
+ *
+ * @param familyNameObj eIDAS familyName attribute information
+ * @return formated user's familyname
+ * @throws EidasAttributeException if NO attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ */
+ protected String processFamilyName(Object familyNameObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (familyNameObj == null || !(familyNameObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
+ }
+
+ return (String) familyNameObj;
+
+ }
+
+ /**
+ * Post-Process the eIDAS pseudonym to ERnB unique identifier.
+ *
+ * @param personalIdObj eIDAS PersonalIdentifierAttribute
+ * @return Unique personal identifier without country-code information
+ * @throws EidasAttributeException if NO attribute is available
+ * @throws EidPostProcessingException if post-processing fails
+ */
+ protected String processPseudonym(Object personalIdObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (personalIdObj == null || !(personalIdObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ }
+
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier((String) personalIdObj);
+
+ return eIdentifier.getThird();
+
+ }
+
+ /**
+ * Set ProviderName and RequestId into eIDAS AuthnRequest.
+ *
+ * @param pendingReq Current pendingRequest
+ * @param authnRequestBuilder AuthnRequest builder
+ */
+ protected void buildProviderNameAndRequesterIdAttribute(IRequest pendingReq, Builder authnRequestBuilder) {
+ final ISpConfiguration spConfig = pendingReq.getServiceProviderConfiguration();
+
+ // set correct SPType for requested target sector
+ final String publicSectorTargetSelector = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_PUBLICSECTOR_TARGETS,
+ Constants.POLICY_DEFAULT_ALLOWED_TARGETS);
+ final Pattern p = Pattern.compile(publicSectorTargetSelector);
+ final Matcher m = p.matcher(spConfig.getAreaSpecificTargetIdentifier());
+ if (m.matches()) {
+ log.debug("Map " + spConfig.getAreaSpecificTargetIdentifier() + " to 'PublicSector'");
+ authnRequestBuilder.spType(SpType.PUBLIC.getValue());
+
+ final String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class);
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME,
+ false)) {
+ //TODO: only for eIDAS ref. node 2.0 and 2.1 because it need 'Providername' for
+ if (StringUtils.isNotEmpty(providerName)) {
+ log.debug("Set 'providername' to: {}", providerName);
+ authnRequestBuilder.providerName(providerName);
+
+ } else {
+ authnRequestBuilder.providerName(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP,
+ Constants.DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP));
+
+ }
+ }
+
+ } else {
+ log.debug("Map " + spConfig.getAreaSpecificTargetIdentifier() + " to 'PrivateSector'");
+ authnRequestBuilder.spType(SpType.PRIVATE.getValue());
+
+ // TODO: switch to RequesterId in further version
+ // set provider name for private sector applications
+ final String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class);
+ if (StringUtils.isNotEmpty(providerName)) {
+ authnRequestBuilder.providerName(providerName);
+
+ }
+
+ authnRequestBuilder.requesterId(
+ generateRequesterId(pendingReq.getRawData(Constants.DATA_REQUESTERID, String.class)));
+
+ }
+ }
+
+ /**
+ * Build LoA based on Service-Provider configuration.
+ *
+ * @param spConfig Current SP configuration
+ * @param authnRequestBuilder AuthnRequest builder
+ */
+ protected void buildLevelOfAssurance(ISpConfiguration spConfig, Builder authnRequestBuilder) {
+ // TODO: set matching mode if eIDAS ref. impl. support this method
+
+ // TODO: update if eIDAS ref. impl. supports exact matching for non-notified LoA
+ // schemes
+ String loa = EaafConstants.EIDAS_LOA_HIGH;
+ if (spConfig.getRequiredLoA() != null) {
+ if (spConfig.getRequiredLoA().isEmpty()) {
+ log.info("No eIDAS LoA requested. Use LoA HIGH as default");
+ } else {
+ if (spConfig.getRequiredLoA().size() > 1) {
+ log.info(
+ "Currently only ONE requested LoA is supported for service provider. Use first one ... ");
+ }
+
+ loa = spConfig.getRequiredLoA().get(0);
+
+ }
+ }
+
+ log.debug("Request eIdAS node with LoA: " + loa);
+ authnRequestBuilder.levelsOfAssuranceValues(Arrays.asList(loa));
+
+ }
+
+ private String generateRequesterId(String requesterId) {
+ if (requesterId != null && basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_REQUESTERID_USE_HASHED_VERSION, true)) {
+ try {
+ log.trace("Building hashed 'requesterId' for private SP ... ");
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ String encodedRequesterId = Base64.getEncoder().encodeToString(
+ digest.digest(requesterId.getBytes(StandardCharsets.UTF_8)));
+ log.debug("Set 'requesterId' for: {} to: {}", requesterId, encodedRequesterId);
+ return encodedRequesterId;
+
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Can NOT generate hashed 'requesterId' from: {}. Use it as it is", requesterId, e);
+
+ }
+
+ }
+
+ return requesterId;
+
+ }
+
+
+ private void buildRequestedAttributes(Builder authnRequestBuilder) {
+ // build and add requested attribute set
+ final Map<String, Boolean> ccSpecificReqAttr = getCountrySpecificRequestedAttributes();
+ log.debug("Get #{} country-specific requested attributes", ccSpecificReqAttr.size());
+
+ final Map<String, Boolean> mdsReqAttr = attrRegistry.getDefaultAttributeSetFromConfiguration();
+ log.trace("Get #{} default requested attributes", mdsReqAttr.size());
+
+ // put it together
+ ccSpecificReqAttr.putAll(mdsReqAttr);
+
+ // convert it to eIDAS attributes
+ final ImmutableAttributeMap reqAttrMap = translateToEidasAttributes(ccSpecificReqAttr);
+ authnRequestBuilder.requestedAttributes(reqAttrMap);
+
+ }
+
+ private ImmutableAttributeMap translateToEidasAttributes(final Map<String, Boolean> requiredAttributes) {
+ final ImmutableAttributeMap.Builder builder = ImmutableAttributeMap.builder();
+ for (final Map.Entry<String, Boolean> attribute : requiredAttributes.entrySet()) {
+ final String name = attribute.getKey();
+ final ImmutableSortedSet<AttributeDefinition<?>> byFriendlyName = attrRegistry
+ .getCoreAttributeRegistry().getByFriendlyName(name);
+ if (!byFriendlyName.isEmpty()) {
+ final AttributeDefinition<?> attributeDefinition = byFriendlyName.first();
+ builder.put(AttributeDefinition.builder(attributeDefinition).required(attribute.getValue()).build());
+
+ } else {
+ log.warn("Can NOT request UNKNOWN attribute: " + attribute.getKey() + " Ignore it!");
+ }
+
+ }
+
+ return builder.build();
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeEidProcessor.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeEidProcessor.java
new file mode 100644
index 00000000..6dc08181
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeEidProcessor.java
@@ -0,0 +1,113 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+import java.util.Map;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+
+
+public class DeEidProcessor extends AbstractEidProcessor {
+ private static final Logger log = LoggerFactory.getLogger(DeEidProcessor.class);
+ private static final String canHandleCC = "DE";
+
+ private int priority = 1;
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ @Override
+ public boolean canHandle(String countryCode) {
+ return countryCode != null && countryCode.equalsIgnoreCase(canHandleCC);
+
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ @Override
+ public String getName() {
+ return "DE-PostProcessor";
+
+ }
+
+ @Override
+ protected String processPseudonym(Object uniqeIdentifierObj) throws EidPostProcessingException,
+ EidasAttributeException {
+ if (uniqeIdentifierObj == null || !(uniqeIdentifierObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ }
+
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier((String) uniqeIdentifierObj);
+
+ log.trace(getName() + " starts processing of attribute: " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ final String result = convertDeIdentifier(eIdentifier.getThird());
+ log.debug(getName() + " finished processing of attribute: " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+
+ return result;
+
+ }
+
+ private String convertDeIdentifier(String hexEncodedDeIdentifier) throws EidPostProcessingException {
+ if (hexEncodedDeIdentifier.length() != 64) {
+ throw new EidPostProcessingException("ernb.03", new Object[] {
+ "Input has wrong length, expected 64 chars" });
+ }
+
+ byte[] data;
+ try {
+ data = Hex.decodeHex(hexEncodedDeIdentifier);
+ final byte[] encoded = Base64.getEncoder().encode(data);
+ return new String(encoded, "UTF-8");
+
+ } catch (final DecoderException | UnsupportedEncodingException e) {
+ throw new EidPostProcessingException("ernb.03", null, e);
+
+ }
+
+
+ }
+
+ @Override
+ protected Map<String, Boolean> getCountrySpecificRequestedAttributes() {
+ return attrRegistry.getAttributeSetFromConfiguration(canHandleCC);
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/GenericEidProcessor.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/GenericEidProcessor.java
new file mode 100644
index 00000000..69949435
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/GenericEidProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GenericEidProcessor extends AbstractEidProcessor {
+
+ private int priority = 0;
+
+ @Override
+ public int getPriority() {
+ return priority;
+
+ }
+
+ @Override
+ public boolean canHandle(String countryCode) {
+ return true;
+
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ @Override
+ public String getName() {
+ return "Default-PostProcessor";
+
+ }
+
+ @Override
+ protected Map<String, Boolean> getCountrySpecificRequestedAttributes() {
+ return new HashMap<>();
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/INationalEidProcessor.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/INationalEidProcessor.java
new file mode 100644
index 00000000..577efbcd
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/INationalEidProcessor.java
@@ -0,0 +1,81 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
+
+import java.util.Map;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+
+public interface INationalEidProcessor {
+
+ /**
+ * Get a friendlyName of this post-processor implementation.
+ *
+ * @return
+ */
+ String getName();
+
+ /**
+ * Get the priority of this eID Post-Processor <br>
+ * If more than one Post-Processor implementations can handle the eID data, the
+ * post-processor with the highest priority are selected. The Default-Processor
+ * has priority '0'
+ *
+ * @return Priority of this handler
+ */
+ int getPriority();
+
+ /**
+ * Check if this postProcessor is sensitive for a specific country.
+ *
+ * @param countryCode of the eID data that should be processed
+ * @return true if this implementation can handle the country, otherwise false
+ *
+ */
+ boolean canHandle(String countryCode);
+
+ /**
+ * Post-Process eIDAS eID data into national format.
+ *
+ * @param eidasAttrMap Map of eIDAS attributes in format friendlyName and
+ * attribute
+ * @throws EidPostProcessingException In case of a post-processing error
+ * @throws EidasAttributeException In case of an invalid eIDAS attribute
+ */
+ ErnbEidData postProcess(Map<String, Object> eidasAttrMap) throws EidPostProcessingException,
+ EidasAttributeException;
+
+ /**
+ * Pre-Process eIDAS Request to national requirements.
+ *
+ * @param pendingReq current pending request
+ * @param authnRequestBuilder eIDAS {@link ILightRequest} builder
+ */
+ void preProcess(IRequest pendingReq, Builder authnRequestBuilder);
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/LuEidProcessor.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/LuEidProcessor.java
new file mode 100644
index 00000000..8402457f
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/LuEidProcessor.java
@@ -0,0 +1,61 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class LuEidProcessor extends AbstractEidProcessor {
+
+
+
+ private static final String canHandleCC = "LU";
+
+ @Getter
+ @Setter
+ private int priority = 1;
+
+ @Override
+ public String getName() {
+ return "LU-PostProcessor";
+
+ }
+
+ @Override
+ public boolean canHandle(String countryCode) {
+ return countryCode != null && countryCode.equalsIgnoreCase(canHandleCC);
+
+ }
+
+ @Override
+ protected void buildProviderNameAndRequesterIdAttribute(IRequest pendingReq, Builder authnRequestBuilder) {
+ super.buildProviderNameAndRequesterIdAttribute(pendingReq, authnRequestBuilder);
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_USE_STATIC_REQUESTERID_FOR_LUX, true)) {
+ String staticName = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP,
+ Constants.DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP);
+ authnRequestBuilder.providerName(staticName);
+ authnRequestBuilder.requesterId(staticName);
+ log.debug("Use static name: {} as 'providerName' and 'RequesterId' for all 'LU' requests ", staticName);
+
+ } else {
+ log.info("Static 'providerName' and 'RequesterId' for country: LU is deactivated");
+
+ }
+
+ }
+
+ @Override
+ protected Map<String, Boolean> getCountrySpecificRequestedAttributes() {
+ return new HashMap<>();
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/NlEidProcessor.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/NlEidProcessor.java
new file mode 100644
index 00000000..2dd22927
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/NlEidProcessor.java
@@ -0,0 +1,54 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class NlEidProcessor extends AbstractEidProcessor {
+
+
+
+ private static final String canHandleCC = "NL";
+
+ @Getter
+ @Setter
+ private int priority = 1;
+
+ @Override
+ public String getName() {
+ return "NL-PostProcessor";
+
+ }
+
+ @Override
+ public boolean canHandle(String countryCode) {
+ return countryCode != null && countryCode.equalsIgnoreCase(canHandleCC);
+
+ }
+
+ protected void buildLevelOfAssurance(ISpConfiguration spConfig, Builder authnRequestBuilder) {
+ super.buildLevelOfAssurance(spConfig, authnRequestBuilder);
+
+ //check requested level
+ if (authnRequestBuilder.build().getLevelOfAssurance().equals(EaafConstants.EIDAS_LOA_LOW)) {
+ log.debug("Upgrade LoA to {}, because NL needs it as minimum.", EaafConstants.EIDAS_LOA_SUBSTANTIAL);
+ authnRequestBuilder.levelsOfAssuranceValues(Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+ }
+ }
+
+ @Override
+ protected Map<String, Boolean> getCountrySpecificRequestedAttributes() {
+ return new HashMap<>();
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java
new file mode 100644
index 00000000..098e76ce
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java
@@ -0,0 +1,211 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.service;
+
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Provider;
+import java.security.cert.X509Certificate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoUnit;
+import java.util.Base64;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jose4j.lang.JoseException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils;
+import at.gv.egiz.eaaf.core.api.IRequest;
+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.exceptions.EaafException;
+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.data.Pair;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Service to build and sign AuthBlock's for E-ID system.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+@Service("authBlockSigningService")
+public class AuthBlockSigningService {
+
+ private static final String KEYSTORE_FRIENDLYNAME = "AuthBlock_Signing";
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ @Autowired
+ IConfiguration basicConfig;
+
+ @Autowired
+ EaafKeyStoreFactory keyStoreFactory;
+
+
+ private Pair<KeyStore, Provider> keyStore;
+
+ /**
+ * Build and sign an AuthBlock for E-ID system.
+ *
+ * @param pendingReq data that should be added into AuthBlock
+ * @return serialized JWS
+ * @throws JsonProcessingException In case of a AuthBlock generation error
+ * @throws JoseException In case of a JWS signing error
+ * @throws EaafException In case of a KeyStore or Key error
+ */
+ public String buildSignedAuthBlock(IRequest pendingReq)
+ throws JsonProcessingException, EaafException, JoseException {
+
+ //TODO: set Challenge to SAML2 requestId to create link between authentication request and authBlock
+
+ // build AuthBlock
+ EidasAuchBlock authBlock = new EidasAuchBlock();
+ authBlock.setChallenge(UUID.randomUUID().toString());
+ authBlock.setTimestamp(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS));
+ authBlock.setUniqueId(pendingReq.getRawData(MsEidasNodeConstants.DATA_REQUESTERID, String.class));
+ authBlock.setPiiTransactionId(pendingReq.getUniquePiiTransactionIdentifier());
+
+ //set Binding PublicKey if available
+ Object bindingPubKey = pendingReq.getRawData(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME);
+ if (bindingPubKey instanceof String) {
+ authBlock.setBindingPublicKey((String) bindingPubKey);
+
+ }
+
+ String jwsPayload = mapper.writeValueAsString(authBlock);
+ log.debug("Building and sign authBlock with data: {}", jwsPayload);
+
+ //sign JWS
+ return JoseUtils
+ .createSignature(keyStore, getKeyAlias(), getKeyPassword(), jwsPayload, false,
+ KEYSTORE_FRIENDLYNAME);
+ }
+
+
+ /**
+ * Get the Base64 encoded PublicKey that is used to sign the AuthBlock.
+ *
+ * @return Base64 encoded PublicKey
+ * @throws EaafKeyAccessException In case of an unknown or invalid key
+ */
+ public String getBase64EncodedPublicKey() throws EaafKeyAccessException {
+ Pair<Key, X509Certificate[]> keyPair = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
+ keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME);
+ return Base64.getEncoder().encodeToString(keyPair.getSecond()[0].getPublicKey().getEncoded());
+
+ }
+
+ @PostConstruct
+ private void initialize() throws KeyStoreException, EaafException {
+ log.debug("Initializing AuthBlock signing service ... ");
+ // read Connector wide config data TODO connector wide!
+ String keyStoreName = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME);
+ String keyStorePw = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD);
+ String keyStorePath = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH);
+ String keyStoreType = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE);
+
+
+ //build new KeyStore configuration
+ KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration();
+ keyStoreConfiguration.setFriendlyName(KEYSTORE_FRIENDLYNAME);
+
+ keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath);
+ keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw);
+ keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType));
+ keyStoreConfiguration.setKeyStoreName(keyStoreName);
+
+ //validate KeyStore configuration
+ keyStoreConfiguration.validate();
+
+ //validate key alias
+ if (StringUtils.isEmpty(getKeyAlias())) {
+ throw new EaafConfigurationException("config.08",
+ new Object[] {MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS});
+
+ }
+
+ //build new KeyStore based on configuration
+ keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfiguration);
+
+ //check if Key is accessible
+ EaafKeyStoreUtils.getPrivateKeyAndCertificates(
+ keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME);
+
+ log.info("AuthBlock signing-service successful initialized");
+
+ }
+
+ private char[] getKeyPassword() {
+ final String value = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD);
+ if (value != null) {
+ return value.trim().toCharArray();
+ }
+
+ return null;
+
+ }
+
+
+ private String getKeyAlias() {
+ return basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS);
+
+ }
+
+ /**
+ * Technical AuthBlock for eIDAS Authentication.
+ *
+ * @author tlenz
+ *
+ */
+ @Data
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private static class EidasAuchBlock {
+
+ @JsonProperty("challenge")
+ private String challenge;
+
+ @JsonProperty("timestamp")
+ @JsonSerialize(using = LocalDateTimeSerializer.class)
+ @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC")
+ private LocalDateTime timestamp;
+
+ @JsonProperty("appId")
+ private String uniqueId;
+
+ @JsonProperty("piiTransactionId")
+ private String piiTransactionId;
+
+ @JsonProperty("bindingPublicKey")
+ private String bindingPublicKey;
+
+ }
+
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/CcSpecificEidProcessingService.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/CcSpecificEidProcessingService.java
new file mode 100644
index 00000000..230d6052
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/CcSpecificEidProcessingService.java
@@ -0,0 +1,135 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+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.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.INationalEidProcessor;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+
+@Service
+public class CcSpecificEidProcessingService implements ICcSpecificEidProcessingService {
+ private static final Logger log = LoggerFactory.getLogger(CcSpecificEidProcessingService.class);
+
+ @Autowired
+ private ApplicationContext context;
+
+ private final List<INationalEidProcessor> handlers = new ArrayList<>();
+
+ @PostConstruct
+ private void initialize() {
+ log.debug("Initialize eID PostProcessing-Service ... ");
+ final Map<String, INationalEidProcessor> postProcessors = context.getBeansOfType(
+ INationalEidProcessor.class);
+ final Iterator<Entry<String, INationalEidProcessor>> iterator = postProcessors.entrySet().iterator();
+ while (iterator.hasNext()) {
+ final Entry<String, INationalEidProcessor> el = iterator.next();
+ log.debug("Find eID-PostProcessor with name: " + el.getKey());
+ handlers.add(el.getValue());
+
+ }
+
+ log.trace("Sorting eID-PostProcessors on priority ... ");
+ Collections.sort(handlers, (thisAuthModule, otherAuthModule) -> {
+ final int thisOrder = thisAuthModule.getPriority();
+ final int otherOrder = otherAuthModule.getPriority();
+ return thisOrder < otherOrder ? 1 : thisOrder == otherOrder ? 0 : -1;
+ });
+
+ log.info("# " + handlers.size() + " eID PostProcessing services are registrated");
+
+ }
+
+ @Override
+ public void preProcess(String selectedCitizenCountry, IRequest pendingReq, Builder authnRequestBuilder)
+ throws EidPostProcessingException {
+ if (StringUtils.isEmpty(selectedCitizenCountry)) {
+ log.info("No CountryCode for eID Pre-Processor. Default Pre-Processor will be used");
+ }
+
+ for (final INationalEidProcessor el : handlers) {
+ if (el.canHandle(selectedCitizenCountry)) {
+ log.debug("Pre-Process eIDAS request for " + selectedCitizenCountry + " by using: " + el.getName());
+ el.preProcess(pendingReq, authnRequestBuilder);
+ return;
+
+ }
+ }
+
+ log.error("NO eID PostProcessor FOUND. Looks like a depentency problem!");
+ throw new EidPostProcessingException("internal.00", null);
+
+ }
+
+ @Override
+ public ErnbEidData postProcess(Map<String, Object> eidasAttrMap) throws EidPostProcessingException,
+ EidasAttributeException {
+ // extract citizen country from eIDAS unique identifier
+ final Object eIdentifierObj = eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ if (eIdentifierObj == null || !(eIdentifierObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ }
+
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier((String) eIdentifierObj);
+ final String citizenCountry = eIdentifier.getFirst();
+
+ if (StringUtils.isEmpty(citizenCountry)) {
+ log.info("No CountryCode for eID PostProcessor. Default-PostProcessor will be used");
+ }
+
+ for (final INationalEidProcessor el : handlers) {
+ if (el.canHandle(citizenCountry)) {
+ log.debug("Post-Process eIDAS eID from " + citizenCountry + " by using: " + el.getName());
+ return el.postProcess(eidasAttrMap);
+
+ }
+ }
+
+ log.error("NO eID PostProcessor FOUND. Looks like a depentency problem!");
+ throw new EidPostProcessingException("internal.00", null);
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasAttributeRegistry.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasAttributeRegistry.java
new file mode 100644
index 00000000..e73491ab
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasAttributeRegistry.java
@@ -0,0 +1,180 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.service;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Service;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import eu.eidas.auth.commons.attribute.AttributeRegistries;
+import eu.eidas.auth.commons.attribute.AttributeRegistry;
+
+@Service("attributeRegistry")
+public class EidasAttributeRegistry {
+ private static final Logger log = LoggerFactory.getLogger(EidasAttributeRegistry.class);
+ @Autowired
+ private IConfigurationWithSP basicConfig;
+
+ private AttributeRegistry coreAttributeRegistry;
+
+ private String eidasAttributesFile;
+ private String additionalAttributesFile;
+
+ @PostConstruct
+ private void initialize() throws RuntimeException {
+ try {
+ if (eidasAttributesFile.isEmpty()) {
+ log.error("Basic eIDAS addribute definition NOT defined");
+ throw new EaafConfigurationException("config.30",
+ new Object[] { "eidas-attributes.xml" });
+
+ }
+
+ boolean additionalAttrAvailabe = false;
+ if (!additionalAttributesFile.isEmpty()) {
+ final File file = new File(additionalAttributesFile);
+ if (file.exists()) {
+ additionalAttrAvailabe = true;
+ }
+
+ }
+
+ if (!additionalAttrAvailabe) {
+ log.info("Start eIDAS ref. impl. Core without additional eIDAS attribute definitions ... ");
+ coreAttributeRegistry = AttributeRegistries.fromFiles(eidasAttributesFile, null);
+
+ } else {
+ // load attribute definitions
+ log.info("Start eIDAS ref. impl. Core with additional eIDAS attribute definitions ... ");
+ coreAttributeRegistry = AttributeRegistries.fromFiles(eidasAttributesFile, null,
+ additionalAttributesFile);
+
+ }
+
+ } catch (final Throwable e) {
+ log.error("Can NOT initialize eIDAS attribute definition.", e);
+ throw new RuntimeException("Can NOT initialize eIDAS attribute definition.", e);
+
+ }
+ }
+
+ public AttributeRegistry getCoreAttributeRegistry() {
+ return coreAttributeRegistry;
+ }
+
+ /**
+ * Get Map of attributes that are requested by default.
+ *
+ * @return Map of AttributeIdentifier, isRequired flag
+ */
+ @NonNull
+ public Map<String, Boolean> getDefaultAttributeSetFromConfiguration() {
+ /*
+ * TODO: select set for representation if mandates should be used. It's an open
+ * task in respect to requested eIDAS attributes and isRequired flag, because
+ * there can be a decision problem in case of natural or legal person
+ * representation! From an Austrian use-case point of view, an Austrian service
+ * provider can support mandates for natural and legal persons at the same time.
+ * However, we CAN NOT request attributes for natural AND legal persons on the
+ * same time, because it's not possible to represent both simultaneously.
+ */
+ final Map<String, String> configAttributes =
+ basicConfig.getBasicConfigurationWithPrefix(
+ Constants.CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_DEFAULT_ONLYNATURAL);
+ return processAttributeInfosFromConfig(configAttributes);
+
+ }
+
+ /**
+ * Get a Map of attributes that are additionally requested for a specific country.
+ *
+ * @param countryCode Country Code
+ * @return Map of AttributeIdentifier, isRequired flag
+ */
+ @NonNull
+ public Map<String, Boolean> getAttributeSetFromConfiguration(String countryCode) {
+
+ /*
+ * TODO: select set for representation if mandates should be used. It's an open
+ * task in respect to requested eIDAS attributes and isRequired flag, because
+ * there can be a decision problem in case of natural or legal person
+ * representation! From an Austrian use-case point of view, an Austrian service
+ * provider can support mandates for natural and legal persons at the same time.
+ * However, we CAN NOT request attributes for natural AND legal persons on the
+ * same time, because it's not possible to represent both simultaneously.
+ */
+ final Map<String, String> configAttributes =
+ basicConfig.getBasicConfigurationWithPrefix(
+ MessageFormat.format(
+ Constants.CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_CC_SPECIFIC_ONLYNATURAL,
+ countryCode.toLowerCase()));
+ return processAttributeInfosFromConfig(configAttributes);
+
+ }
+
+ private Map<String, Boolean> processAttributeInfosFromConfig(Map<String, String> configAttributes) {
+
+ final Map<String, Boolean> result = new HashMap<>();
+ for (final String el : configAttributes.values()) {
+ if (StringUtils.isNotEmpty(el.trim())) {
+ final List<String> attrDef = KeyValueUtils.getListOfCsvValues(el.trim());
+ boolean isRequired = false;
+ if (attrDef.size() == 2) {
+ isRequired = Boolean.parseBoolean(attrDef.get(1));
+ }
+
+ result.put(attrDef.get(0), isRequired);
+
+ }
+ }
+
+ log.trace("Load #" + result.size() + " requested attributes from configuration");
+ return result;
+
+ }
+
+ public void setEidasAttributesFile(String eidasAttributesFile) {
+ this.eidasAttributesFile = eidasAttributesFile;
+ }
+
+ public void setAdditionalAttributesFile(String additionalAttributesFile) {
+ this.additionalAttributesFile = additionalAttributesFile;
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasDataStore.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasDataStore.java
new file mode 100644
index 00000000..549aa65c
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/EidasDataStore.java
@@ -0,0 +1,363 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.service;
+
+//import java.io.File;
+//import java.io.IOException;
+//import java.sql.Connection;
+//import java.sql.DriverManager;
+//import java.sql.PreparedStatement;
+//import java.sql.ResultSet;
+//import java.sql.SQLException;
+//import java.sql.Statement;
+//import java.time.Instant;
+//import java.util.Properties;
+//
+//import javax.annotation.PostConstruct;
+//
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Component;
+//import org.sqlite.SQLiteConfig;
+//import org.sqlite.SQLiteConfig.LockingMode;
+//import org.sqlite.SQLiteConfig.SynchronousMode;
+//import org.sqlite.SQLiteErrorCode;
+//
+//import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+//import at.asitplus.eidas.specific.modules.auth.eidas.v2.DAO.eIDASPersonalIdStoreDAO;
+//import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SQLiteServiceException;
+//import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+//import at.gv.egiz.eaaf.core.impl.data.Pair;
+//import at.gv.egiz.eaaf.core.impl.data.Trible;
+//
+//@Component
+//@Deprecated
+//public class EidasDataStore {
+//
+// private static final String SQLITE_JDBC_DRIVER_CLASS = "org.sqlite.JDBC";
+// private static final String SQLITE_CONNECTION_PARAM = "jdbc:sqlite:%s";
+// private static final boolean sleep = true;
+// private static final int howLongToSleepOnBusyLock_ = 100;
+//
+// private static final Logger log = LoggerFactory.getLogger(EidasDataStore.class);
+//
+// @Autowired
+// private IConfiguration basicConfig;
+//
+// private String connectionUrl;
+// private Connection conn = null;
+//
+// @PostConstruct
+// private void initialize() throws SQLiteServiceException {
+// try {
+// final String sqlLiteDbUrl = basicConfig.getBasicConfiguration(
+// Constants.CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_SQLLITEDATASTORE_URL,
+// basicConfig.getConfigurationRootDirectory().toString() + "/sqlite/database.db"
+//
+// );
+//
+// log.info("Use SQLite database with URL: " + sqlLiteDbUrl);
+//
+// // check if SQLite lib is in Classpath
+// Class.forName(SQLITE_JDBC_DRIVER_CLASS);
+//
+// // open DB connection
+// boolean isNewFileCreated = false;
+//
+// // open file or create file if not already exists
+// final File dbFile = new File(sqlLiteDbUrl);
+// if (!dbFile.exists()) {
+// log.info("SQLite database does not exist. Creating new database file ... ");
+// dbFile.createNewFile();
+// isNewFileCreated = true;
+//
+// }
+//
+// // open database connection
+// connectionUrl = String.format(SQLITE_CONNECTION_PARAM, dbFile.getPath());
+//
+// // create DB scheme if new DB file was created
+// if (isNewFileCreated) {
+// executeUpdate(startConnection().createStatement(), eIDASPersonalIdStoreDAO.CREATE);
+// log.debug("SQLite db scheme created");
+//
+// }
+//
+// } catch (final ClassNotFoundException e) {
+// log.warn("Can NOT initialize SQLite database for temporarly identity mapping. ", e);
+// throw new SQLiteServiceException("internal.05", new Object[] { e.getMessage() }, e);
+//
+// } catch (SQLException | IOException e) {
+// log.warn("Can NOT initialize SQLite database for temporarly identity mapping. ", e);
+// throw new SQLiteServiceException("internal.05", new Object[] { e.getMessage() }, e);
+//
+// }
+//
+// }
+//
+// /**
+// * Store a mapping entry with eIDAS personal identifier (source country /
+// * destination country / personal identifier) and the identifier that is used
+// * for ERnB communication.
+// *
+// * @param transactionId Id of this authentication transaction
+// * @param eidasId eIDAS personal identifier without country prefixes
+// * @param ernbId personal identifier that is used to request the ERnB
+// * @throws SQLiteServiceException In case of a database error
+// */
+// public void storeNationalId(String transactionId, Trible<String, String, String> eidasId, String ernbId)
+// throws SQLiteServiceException {
+// try {
+// final PreparedStatement preStatment = startConnection().prepareStatement(
+// eIDASPersonalIdStoreDAO.INSERT,
+// Statement.RETURN_GENERATED_KEYS);
+//
+// for (int i = 1; i <= eIDASPersonalIdStoreDAO.TABLE_COLS.size(); i++) {
+// final Pair<String, eIDASPersonalIdStoreDAO.T> col = eIDASPersonalIdStoreDAO.TABLE_COLS.get(i - 1);
+// if (col.getFirst().equals(eIDASPersonalIdStoreDAO.COLS.timestamp.name())) {
+// preStatment.setDate(i, new java.sql.Date(Instant.now().toEpochMilli()));
+// } else if (col.getFirst().equals(eIDASPersonalIdStoreDAO.COLS.transactionId.name())) {
+// preStatment.setString(i, transactionId);
+// } else if (col.getFirst().equals(eIDASPersonalIdStoreDAO.COLS.eidasId.name())) {
+// preStatment.setString(i, eidasId.getThird());
+// } else if (col.getFirst().equals(eIDASPersonalIdStoreDAO.COLS.eidasSourceCountry.name())) {
+// preStatment.setString(i, eidasId.getFirst());
+// } else if (col.getFirst().equals(eIDASPersonalIdStoreDAO.COLS.eidasDestinationCountry.name())) {
+// preStatment.setString(i, eidasId.getSecond());
+// } else if (col.getFirst().equals(eIDASPersonalIdStoreDAO.COLS.ernbId.name())) {
+// preStatment.setString(i, ernbId);
+// } else {
+// log.warn("SQLite table:" + eIDASPersonalIdStoreDAO.NAME + " contains no col with name:" + col
+// .getFirst());
+// }
+//
+// }
+//
+// // execute SQL query
+// final int sqlResult = preStatment.executeUpdate();
+//
+// if (sqlResult != 1) {
+// log.warn("SQLite query execution FAILED!");
+// throw new SQLiteServiceException("internal.06", new Object[] { "Queryresult is '-1'" });
+//
+// }
+//
+// } catch (SQLiteServiceException | SQLException e) {
+// log.warn("SQLite query execution FAILED!", e);
+// throw new SQLiteServiceException("internal.05", new Object[] { e.getMessage() }, e);
+//
+// }
+//
+// }
+//
+// /**
+// * Get the ERnB related national identifier from mapping database.
+// *
+// * @param eidasId eIDAS related identifier
+// * @return Mapped ERnB identifier
+// * @throws SQLiteServiceException In case of a database error
+// */
+// public String getErnbNationalId(Trible<String, String, String> eidasId) throws SQLiteServiceException {
+// try {
+// final PreparedStatement preStatment = startConnection().prepareStatement(
+// eIDASPersonalIdStoreDAO.SELECT_BY_EIDAS_RAW_ID,
+// Statement.RETURN_GENERATED_KEYS);
+//
+// preStatment.setString(1, eidasId.getThird());
+// preStatment.setString(2, eidasId.getFirst());
+//
+// final ResultSet rs = preStatment.executeQuery();
+//
+// if (!rs.next()) {
+// return null;
+// } else {
+// return rs.getString(eIDASPersonalIdStoreDAO.COLS.ernbId.name());
+// }
+//
+// } catch (SQLiteServiceException | SQLException e) {
+// log.warn("SQLite query execution FAILED!", e);
+// throw new SQLiteServiceException("internal.05", new Object[] { e.getMessage() }, e);
+//
+// }
+//
+// }
+//
+// /**
+// * Get the eIDAS identifier from an ERnB identifier.
+// *
+// * @param ernbId ERnB specific identifier
+// * @return eIDAS unqiue identifier
+// * @throws SQLiteServiceException In case of a database error
+// */
+// public String getEidasRawNationalId(String ernbId) throws SQLiteServiceException {
+// try {
+// final PreparedStatement preStatment = startConnection().prepareStatement(
+// eIDASPersonalIdStoreDAO.SELECT_BY_ERNB_ID,
+// Statement.RETURN_GENERATED_KEYS);
+//
+// preStatment.setString(1, ernbId);
+//
+// final ResultSet rs = preStatment.executeQuery();
+//
+// if (!rs.next()) {
+// return null;
+// } else {
+// return rs.getString(eIDASPersonalIdStoreDAO.COLS.eidasId.name());
+// }
+//
+// } catch (SQLiteServiceException | SQLException e) {
+// log.warn("SQLite query execution FAILED!", e);
+// throw new SQLiteServiceException("internal.05", new Object[] { e.getMessage() }, e);
+//
+// }
+//
+// }
+//
+// private Connection startConnection() throws SQLiteServiceException {
+// int i = howLongToSleepOnBusyLock_;
+//
+// while (true) {
+// try {
+// if (conn == null) {
+// log.info("Initializing SQLite database with URL: " + connectionUrl + " ... ");
+// conn = DriverManager.getConnection(connectionUrl, getConnectionProperties());
+//
+// } else {
+// if (!conn.isValid(10)) {
+// log.info("SQLite connection is not valid any more --> restarting connection ...");
+// conn.close();
+// conn = DriverManager.getConnection(connectionUrl, getConnectionProperties());
+// }
+// }
+//
+// log.info("SQLite database connected");
+// return conn;
+//
+// } catch (final SQLException e) {
+// final String msg = e.getLocalizedMessage();
+// if (isBusyLocked(e)) {
+// log.warn(msg, e);
+// try {
+// if (sleep) {
+// Thread.sleep(i++);
+// }
+//
+// } catch (final InterruptedException e1) {
+// throw new SQLiteServiceException("internal.05", new Object[] { e1.getMessage() }, e1);
+//
+// }
+// continue;
+//
+// }
+// throw new SQLiteServiceException("internal.05", new Object[] { e.getMessage() }, e);
+//
+// }
+// }
+// }
+//
+// /*
+// * SQLite query code
+// */
+//
+// protected Properties getConnectionProperties() {
+// final SQLiteConfig config = new SQLiteConfig();
+// config.enforceForeignKeys(true);
+// config.setCacheSize(8000);
+// config.setLockingMode(LockingMode.NORMAL);
+// config.setSharedCache(false);
+// config.setReadUncommited(true);
+// config.setSynchronous(SynchronousMode.NORMAL);
+// return config.toProperties();
+//
+// }
+//
+// private int executeUpdate(Statement statement, String sql) throws SQLiteServiceException {
+// final int i = 10;
+//
+// int rc = -1;
+// while (true) {
+// try {
+// rc = statement.executeUpdate(sql);
+// break;
+//
+// } catch (final SQLException e) {
+// try {
+// if (executeUpdateError(e, i)) {
+// continue;
+// } else {
+// throw new SQLiteServiceException("internal.06",
+// new Object[] { e.getMessage() }, e);
+// }
+//
+// } catch (final SQLiteServiceException e1) {
+// log.warn("\n" + sql + "\n" + e1.getMessage());
+// throw e1;
+//
+// }
+// }
+// }
+//
+// return rc;
+//
+// }
+//
+// private boolean isBusyLocked(SQLException e) {
+// final int eC = e.getErrorCode();
+//
+// if (eC == SQLiteErrorCode.SQLITE_LOCKED.code
+// || eC == SQLiteErrorCode.SQLITE_BUSY.code) {
+// log.trace("SQLite db is busy looked");
+// return true;
+//
+// }
+//
+// final String msg = e.getMessage();
+// if (msg.contains("[SQLITE_LOCKED]") || msg.contains("[SQLITE_BUSY]")) {
+// log.trace("SQLite db is busy looked");
+// return true;
+// }
+//
+// return false;
+// }
+//
+// private boolean executeUpdateError(SQLException e, int theadSleepCounter) throws SQLiteServiceException {
+// if (isBusyLocked(e)) {
+// try {
+// if (sleep) {
+// Thread.sleep(theadSleepCounter++);
+// }
+//
+// } catch (final InterruptedException e1) {
+// throw new SQLiteServiceException("internal.05", new Object[] { e1.getMessage() }, e1);
+//
+// }
+//
+// return true;
+// }
+//
+// return false;
+//
+// }
+//}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/ICcSpecificEidProcessingService.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/ICcSpecificEidProcessingService.java
new file mode 100644
index 00000000..ebbc15e4
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/ICcSpecificEidProcessingService.java
@@ -0,0 +1,61 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.service;
+
+import java.util.Map;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+
+public interface ICcSpecificEidProcessingService {
+
+ /**
+ * Post-process eIDAS eID attributes into national format.
+ *
+ * @param eidasAttrMap Map of eIDAS attributes in format friendlyName and
+ * attribute
+ *
+ * @return eID attributes for SZR request
+ * @throws EidPostProcessingException In case of a post-processing error
+ * @throws EidasAttributeException In case of an invalid eIDAS attribute value
+ */
+ ErnbEidData postProcess(Map<String, Object> eidasAttrMap) throws EidPostProcessingException,
+ EidasAttributeException;
+
+ /**
+ * Pre Process eIDAS request into national requirements.
+ *
+ * @param selectedCC Citizen Country from selection
+ * @param pendingReq current pending request
+ * @param authnRequestBuilder eIDAS {@link ILightRequest} builder
+ * @throws EidPostProcessingException In case of a pre-processing error
+ */
+ void preProcess(String selectedCC, IRequest pendingReq, Builder authnRequestBuilder)
+ throws EidPostProcessingException;
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java
new file mode 100644
index 00000000..1f5837d6
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java
@@ -0,0 +1,522 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.szr;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.handler.Handler;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.jaxws.DispatchImpl;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.apache.xpath.XPathAPI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.LoggingHandler;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.XmlNamespaceConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
+import szrservices.GetBPK;
+import szrservices.GetBPKResponse;
+import szrservices.GetIdentityLinkEidas;
+import szrservices.GetIdentityLinkEidasResponse;
+import szrservices.IdentityLinkType;
+import szrservices.JwsHeaderParam;
+import szrservices.ObjectFactory;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SZRException_Exception;
+import szrservices.SignContent;
+import szrservices.SignContentEntry;
+import szrservices.SignContentResponseType;
+
+
+@Service("SZRClientForeIDAS")
+public class SzrClient {
+ private static final Logger log = LoggerFactory.getLogger(SzrClient.class);
+
+ private static final String CLIENT_DEFAULT = "DefaultClient";
+ private static final String CLIENT_RAW = "RawClient";
+
+ private static final String ATTR_NAME_VSZ = "urn:eidgvat:attributes.vsz.value";
+ private static final String ATTR_NAME_PUBKEYS = "urn:eidgvat:attributes.user.pubkeys";
+ private static final String ATTR_NAME_STATUS = "urn:eidgvat:attributes.eid.status";
+ private static final String KEY_BC_BIND = "bcBindReq";
+ private static final String JOSE_HEADER_USERCERTPINNING_TYPE = "urn:at.gv.eid:bindtype";
+ private static final String JOSE_HEADER_USERCERTPINNING_EIDASBIND = "urn:at.gv.eid:eidasBind";
+ public static final String ATTR_NAME_MDS = "urn:eidgvat:mds";
+
+ @Autowired
+ private IConfiguration basicConfig;
+
+ // client for anything, without identitylink
+ private SZR szr = null;
+
+ // RAW client is needed for identitylink
+ private Dispatch<Source> dispatch = null;
+
+ private SzrService szrService = null;
+ private String szrUrl = null;
+ private QName qname = null;
+
+ final ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * Get IdentityLink of a person.
+ *
+ * @param personInfo Person identification information
+ * @return IdentityLink
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public IdentityLinkType getIdentityLinkInRawMode(PersonInfoType personInfo)
+ throws SzrCommunicationException {
+ try {
+ final GetIdentityLinkEidas getIdl = new GetIdentityLinkEidas();
+ getIdl.setPersonInfo(personInfo);
+
+ final JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
+ final Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ jaxbMarshaller.marshal(getIdl, outputStream);
+ outputStream.flush();
+
+ final Source source = new StreamSource(new ByteArrayInputStream(outputStream.toByteArray()));
+ outputStream.close();
+
+ log.trace("Requesting SZR ... ");
+ final Source response = dispatch.invoke(source);
+ log.trace("Receive RAW response from SZR");
+
+ final byte[] szrResponse = sourceToByteArray(response);
+ final GetIdentityLinkEidasResponse jaxbElement = (GetIdentityLinkEidasResponse) jaxbContext
+ .createUnmarshaller().unmarshal(new ByteArrayInputStream(szrResponse));
+
+ // build response
+ log.trace(new String(szrResponse, "UTF-8"));
+
+ // ok, we have success
+ final Document doc = DomUtils.parseDocument(
+ new ByteArrayInputStream(szrResponse),
+ true,
+ XmlNamespaceConstants.ALL_SCHEMA_LOCATIONS + " " + Constants.SZR_SCHEMA_LOCATIONS,
+ null, null);
+ final String xpathExpression = "//saml:Assertion";
+ final Element nsNode = doc.createElementNS("urn:oasis:names:tc:SAML:1.0:assertion", "saml:NSNode");
+
+ log.trace("Selecting signed doc " + xpathExpression);
+ final Element documentNode = (Element) XPathAPI.selectSingleNode(doc,
+ xpathExpression, nsNode);
+ log.trace("Signed document: " + DomUtils.serializeNode(documentNode));
+
+ final IdentityLinkType idl = new IdentityLinkType();
+ idl.setAssertion(documentNode);
+ idl.setPersonInfo(jaxbElement.getGetIdentityLinkReturn().getPersonInfo());
+
+ return idl;
+
+ } catch (final Exception e) {
+ log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e);
+ throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Get bPK of person.
+ *
+ * @param personInfo Person identification information
+ * @param target requested bPK target
+ * @param vkz Verfahrenskennzeichen
+ * @return bPK for this person
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public List<String> getBpk(PersonInfoType personInfo, String target, String vkz)
+ throws SzrCommunicationException {
+ try {
+ final GetBPK parameters = new GetBPK();
+ parameters.setPersonInfo(personInfo);
+ parameters.getBereichsKennung().add(target);
+ parameters.setVKZ(vkz);
+ final GetBPKResponse result = this.szr.getBPK(parameters);
+
+ return result.getGetBPKReturn();
+
+ } catch (final SZRException_Exception e) {
+ log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e);
+ throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Request a encryped baseId from SRZ.
+ *
+ * @param personInfo Minimum dataset of person
+ * @return encrypted baseId
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public String getEncryptedStammzahl(final PersonInfoType personInfo)
+ throws SzrCommunicationException {
+
+ final String resp;
+ try {
+ resp = this.szr.getStammzahlEncrypted(personInfo, true);
+ } catch (SZRException_Exception e) {
+ throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);
+ }
+
+ if (StringUtils.isEmpty(resp)) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"Stammzahl response empty"}); // TODO error handling
+ }
+
+ return resp;
+
+ }
+
+ /**
+ * Sign an eidasBind data-structure that combines vsz with user's pubKey and E-ID status.
+ *
+ * @param vsz encryped baseId
+ * @param bindingPubKey binding PublikKey as PKCS1# (ASN.1) container
+ * @param eidStatus Status of the E-ID
+ * @param eidData eID information that was used for ERnP registration
+ * @return bPK for this person
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public String getEidsaBind(final String vsz, final String bindingPubKey, final String eidStatus,
+ ErnbEidData eidData)throws SzrCommunicationException {
+
+ final Map<String, Object> eidsaBindMap = new HashMap<>();
+ eidsaBindMap.put(ATTR_NAME_VSZ, vsz);
+ eidsaBindMap.put(ATTR_NAME_STATUS, eidStatus);
+ eidsaBindMap.put(ATTR_NAME_PUBKEYS, Arrays.asList(bindingPubKey));
+ eidsaBindMap.put(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, eidData.getCitizenCountryCode());
+ injectMdsIfAvailableAndActive(eidsaBindMap, eidData);
+
+ try {
+ final String serializedEidasBind = mapper.writeValueAsString(eidsaBindMap);
+ final SignContent req = new SignContent();
+ final SignContentEntry eidasBindInfo = new SignContentEntry();
+ eidasBindInfo.setKey(KEY_BC_BIND);
+ eidasBindInfo.setValue(serializedEidasBind);
+ req.getIn().add(eidasBindInfo);
+ req.setAppendCert(false);
+ final JwsHeaderParam eidasBindJoseHeader = new JwsHeaderParam();
+ eidasBindJoseHeader.setKey(JOSE_HEADER_USERCERTPINNING_TYPE);
+ eidasBindJoseHeader.setValue(JOSE_HEADER_USERCERTPINNING_EIDASBIND);
+ req.getJWSHeaderParam().add(eidasBindJoseHeader);
+
+ log.trace("Requesting SZR to sign bcBind datastructure ... ");
+ final SignContentResponseType resp = szr.signContent(req.isAppendCert(), req.getJWSHeaderParam(), req.getIn());
+ log.trace("Receive SZR response on bcBind siging operation ");
+
+ if (resp == null || resp.getOut() == null
+ || resp.getOut().isEmpty()
+ || StringUtils.isEmpty(resp.getOut().get(0).getValue())) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"BcBind response empty"});
+ }
+
+ return resp.getOut().get(0).getValue();
+
+ } catch (final JsonProcessingException | SZRException_Exception e) {
+ log.warn("Requesting bcBind by using SZR FAILED. Reason: {}", e.getMessage(), null, e);
+ throw new SzrCommunicationException("ernb.02",
+ new Object[]{e.getMessage()}, e);
+ }
+ }
+
+ @PostConstruct
+ private void initialize() {
+ log.info("Starting SZR-Client initialization .... ");
+ final URL url = SzrClient.class.getResource("/szr_client/SZR_v4.0.wsdl");
+
+ final boolean useTestSzr = basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE,
+ true);
+
+ if (useTestSzr) {
+ log.debug("Initializing SZR test environment configuration.");
+ qname = SzrService.SZRTestumgebung;
+ szrService = new SzrService(url, new QName("urn:SZRServices", "SZRService"));
+ szr = szrService.getSzrTestumgebung();
+ szrUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_TEST);
+
+ } else {
+ log.debug("Initializing SZR productive configuration.");
+ qname = SzrService.SZRProduktionsumgebung;
+ szrService = new SzrService(url, new QName("urn:SZRServices", "SZRService"));
+ szr = szrService.getSzrProduktionsumgebung();
+ szrUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_PROD);
+
+ }
+
+ // create raw client;
+ dispatch = szrService.createDispatch(qname, Source.class, javax.xml.ws.Service.Mode.PAYLOAD);
+
+ if (StringUtils.isEmpty(szrUrl)) {
+ log.error("No SZR service-URL found. SZR-Client initalisiation failed.");
+ throw new RuntimeException("No SZR service URL found. SZR-Client initalisiation failed.");
+
+ }
+
+ // check if Clients can be initialized
+ if (szr == null) {
+ log.error("SZR " + CLIENT_DEFAULT + " is 'NULL'. Something goes wrong");
+ throw new RuntimeException("SZR " + CLIENT_DEFAULT + " is 'NULL'. Something goes wrong");
+
+ }
+ if (dispatch == null) {
+ log.error("SZR " + CLIENT_RAW + " is 'NULL'. Something goes wrong");
+ throw new RuntimeException("SZR " + CLIENT_RAW + " is 'NULL'. Something goes wrong");
+
+ }
+
+ // inject handler
+ log.info("Use SZR service-URL: " + szrUrl);
+ injectBindingProvider((BindingProvider) szr, CLIENT_DEFAULT);
+ injectBindingProvider(dispatch, CLIENT_RAW);
+
+ // inject http parameters and SSL context
+ log.debug("Inject HTTP client settings ... ");
+ injectHttpClient(szr, CLIENT_DEFAULT);
+ injectHttpClient(dispatch, CLIENT_RAW);
+
+ log.info("SZR-Client initialization successfull");
+ }
+
+ private void injectHttpClient(Object raw, String clientType) {
+ // extract client from implementation
+ Client client = null;
+ if (raw instanceof DispatchImpl<?>) {
+ client = ((DispatchImpl<?>) raw).getClient();
+ } else if (raw instanceof Client) {
+ client = ClientProxy.getClient(raw);
+ } else {
+ throw new RuntimeException("SOAP Client for SZR connection is of UNSUPPORTED type: " + raw.getClass()
+ .getName());
+ }
+
+ // set basic connection policies
+ final HTTPConduit http = (HTTPConduit) client.getConduit();
+
+ // set timeout policy
+ final HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+ httpClientPolicy.setConnectionTimeout(
+ Integer.parseInt(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_CONNECTION,
+ Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_CONNECTION)) * 1000);
+ httpClientPolicy.setReceiveTimeout(
+ Integer.parseInt(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_RESPONSE,
+ Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_RESPONSE)) * 1000);
+ http.setClient(httpClientPolicy);
+
+ // inject SSL context in case of https
+ if (szrUrl.toLowerCase().startsWith("https")) {
+ log.debug("Adding SSLContext to client: " + clientType + " ... ");
+ final TLSClientParameters tlsParams = new TLSClientParameters();
+ tlsParams.setSSLSocketFactory(createSslContext(clientType).getSocketFactory());
+ http.setTlsClientParameters(tlsParams);
+ log.info("SSLContext initialized for client: " + clientType);
+
+ }
+
+ }
+
+ private void injectBindingProvider(BindingProvider bindingProvider, String clientType) {
+ final Map<String, Object> requestContext = bindingProvider.getRequestContext();
+ requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, szrUrl);
+
+ log.trace("Adding JAX-WS request/response trace handler to client: " + clientType);
+ List<Handler> handlerList = bindingProvider.getBinding().getHandlerChain();
+ if (handlerList == null) {
+ handlerList = new ArrayList<>();
+ bindingProvider.getBinding().setHandlerChain(handlerList);
+
+ }
+
+ // add logging handler to trace messages if required
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_TRACEMESSAGES,
+ false)) {
+ final LoggingHandler loggingHandler = new LoggingHandler();
+ handlerList.add(loggingHandler);
+
+ }
+ bindingProvider.getBinding().setHandlerChain(handlerList);
+ }
+
+ private SSLContext createSslContext(String clientType) {
+ try {
+ final SSLContext context = SSLContext.getInstance("TLS");
+
+ // initialize key-mangager for SSL client-authentication
+ KeyManager[] keyManager = null;
+ final String keyStorePath = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PATH);
+ final String keyStorePassword = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PASSWORD);
+ if (StringUtils.isNotEmpty(keyStorePath)) {
+ log.trace("Find keyStore path: " + keyStorePath + " Injecting SSL client certificate ... ");
+ try {
+ final KeyStore keyStore = KeyStoreUtils.loadKeyStore(
+ FileUtils.makeAbsoluteUrl(keyStorePath, basicConfig.getConfigurationRootDirectory()),
+ keyStorePassword);
+
+ final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(keyStore, keyStorePassword.toCharArray());
+ keyManager = kmf.getKeyManagers();
+ log.debug("SSL client certificate injected to client: " + clientType);
+
+ } catch (KeyStoreException | IOException | UnrecoverableKeyException e) {
+ log.error("Can NOT load SSL client certificate from path: " + keyStorePath);
+ throw new RuntimeException("Can NOT load SSL client certificate from path: " + keyStorePath, e);
+
+ }
+ } else {
+ log.debug(
+ "No KeyStore for SSL Client Auth. found. Initializing SSLContext without authentication ... ");
+
+ }
+
+ // initialize SSL TrustStore
+ TrustManager[] trustManager = null;
+ final String trustStorePath = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PATH);
+ final String trustStorePassword = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PASSWORD);
+ if (StringUtils.isNotEmpty(trustStorePath)) {
+ log.trace("Find trustStore path: " + trustStorePath + " Injecting SSL TrustStore ... ");
+ try {
+ final KeyStore trustStore = KeyStoreUtils.loadKeyStore(
+ FileUtils.makeAbsoluteUrl(trustStorePath, basicConfig.getConfigurationRootDirectory()),
+ trustStorePassword);
+
+ final TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(trustStore);
+ trustManager = tmf.getTrustManagers();
+ log.debug("SSL TrustStore injected to client: " + clientType);
+
+ } catch (KeyStoreException | IOException e) {
+ log.error("Can NOT open SSL TrustStore from path: " + trustStorePath);
+ throw new RuntimeException("Can NOT open SSL TrustStore from path: " + trustStorePath, e);
+
+ }
+
+ } else {
+ log.debug("No custom SSL TrustStore found. Initializing SSLContext with JVM default truststore ... ");
+
+ }
+
+ context.init(keyManager, trustManager, new SecureRandom());
+ return context;
+
+ } catch (NoSuchAlgorithmException | KeyManagementException e) {
+ log.error("SSLContext initialization FAILED.", e);
+ throw new RuntimeException("SSLContext initialization FAILED.", e);
+
+ }
+
+ }
+
+ private void injectMdsIfAvailableAndActive(Map<String, Object> eidsaBindMap, ErnbEidData eidData) {
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SET_MDS_TO_EIDASBIND, false)) {
+ log.info("Injecting MDS into eidasBind ... ");
+ final Map<String, Object> mds = new HashMap<>();
+ mds.put(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, eidData.getFamilyName());
+ mds.put(PvpAttributeDefinitions.GIVEN_NAME_NAME, eidData.getGivenName());
+ mds.put(PvpAttributeDefinitions.BIRTHDATE_NAME, eidData.getFormatedDateOfBirth());
+ eidsaBindMap.put(ATTR_NAME_MDS, mds);
+
+ }
+ }
+
+ private byte[] sourceToByteArray(Source result) throws TransformerException {
+ final TransformerFactory factory = TransformerFactory.newInstance();
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ final Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty("omit-xml-declaration", "yes");
+ transformer.setOutputProperty("method", "xml");
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final StreamResult streamResult = new StreamResult();
+ streamResult.setOutputStream(out);
+ transformer.transform(result, streamResult);
+ return out.toByteArray();
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrService.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrService.java
new file mode 100644
index 00000000..dde868b1
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrService.java
@@ -0,0 +1,164 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.szr;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.WebEndpoint;
+import javax.xml.ws.WebServiceClient;
+import javax.xml.ws.WebServiceFeature;
+
+import szrservices.SZR;
+
+/**
+ * This class was generated by Apache CXF 3.1.16 2018-07-10T09:36:01.466+02:00
+ * Generated source version: 3.1.16
+ *
+ */
+@WebServiceClient(name = "SZRService",
+ wsdlLocation = "./src/main/resources/szr_client/SZR-1.WSDL",
+ targetNamespace = "urn:SZRServices")
+public class SzrService extends Service {
+
+ public static final URL WSDL_LOCATION;
+
+ public static final QName SERVICE = new QName("urn:SZRServices", "SZRService");
+ public static final QName SZRProduktionsumgebung = new QName("urn:SZRServices", "SZRProduktionsumgebung");
+ public static final QName SZRTestumgebung = new QName("urn:SZRServices", "SZRTestumgebung");
+ public static final QName SZRBusinesspartnerTestumgebung = new QName("urn:SZRServices",
+ "SZRBusinesspartnerTestumgebung");
+
+ static {
+ URL url = SzrService.class.getResource("./src/main/resources/szr_client/SZR-1.WSDL");
+ if (url == null) {
+ url = SzrService.class.getClassLoader().getResource("/szr_client/SZR-1.WSDL");
+ }
+ if (url == null) {
+ java.util.logging.Logger.getLogger(SzrService.class.getName())
+ .log(java.util.logging.Level.INFO,
+ "Can not initialize the default wsdl from {0}", "/szr_client/SZR-1.WSDL");
+ }
+ WSDL_LOCATION = url;
+
+ }
+
+ public SzrService(URL wsdlLocation) {
+ super(wsdlLocation, SERVICE);
+ }
+
+ public SzrService(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public SzrService() {
+ super(WSDL_LOCATION, SERVICE);
+ }
+
+ public SzrService(WebServiceFeature... features) {
+ super(WSDL_LOCATION, SERVICE, features);
+ }
+
+ public SzrService(URL wsdlLocation, WebServiceFeature... features) {
+ super(wsdlLocation, SERVICE, features);
+ }
+
+ public SzrService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+ /**
+ * Get SZR Web-Service.
+ *
+ * @return returns SZR
+ */
+ @WebEndpoint(name = "SZRProduktionsumgebung")
+ public SZR getSzrProduktionsumgebung() {
+ return super.getPort(SZRProduktionsumgebung, SZR.class);
+ }
+
+ /**
+ * Get SZR Web-Service.
+ *
+ * @param features A list of {@link javax.xml.ws.WebServiceFeature} to configure
+ * on the proxy. Supported features not in the
+ * <code>features</code> parameter will have their default
+ * values.
+ * @return returns SZR
+ */
+ @WebEndpoint(name = "SZRProduktionsumgebung")
+ public SZR getSzrProduktionsumgebung(WebServiceFeature... features) {
+ return super.getPort(SZRProduktionsumgebung, SZR.class, features);
+ }
+
+ /**
+ *Get SZR Web-Service.
+ *
+ * @return returns SZR
+ */
+ @WebEndpoint(name = "SZRTestumgebung")
+ public SZR getSzrTestumgebung() {
+ return super.getPort(SZRTestumgebung, SZR.class);
+ }
+
+ /**
+ * Get SZR Web-Service.
+ *
+ * @param features A list of {@link javax.xml.ws.WebServiceFeature} to configure
+ * on the proxy. Supported features not in the
+ * <code>features</code> parameter will have their default
+ * values.
+ * @return returns SZR
+ */
+ @WebEndpoint(name = "SZRTestumgebung")
+ public SZR getSzrTestumgebung(WebServiceFeature... features) {
+ return super.getPort(SZRTestumgebung, SZR.class, features);
+ }
+
+ /**
+ * Get SZR Web-Service.
+ *
+ * @return returns SZR
+ */
+ @WebEndpoint(name = "SZRBusinesspartnerTestumgebung")
+ public SZR getSzrBusinesspartnerTestumgebung() {
+ return super.getPort(SZRBusinesspartnerTestumgebung, SZR.class);
+ }
+
+ /**
+ * Get SZR Web-Service.
+ *
+ * @param features A list of {@link javax.xml.ws.WebServiceFeature} to configure
+ * on the proxy. Supported features not in the
+ * <code>features</code> parameter will have their default
+ * values.
+ * @return returns SZR
+ */
+ @WebEndpoint(name = "SZRBusinesspartnerTestumgebung")
+ public SZR getSzrBusinesspartnerTestumgebung(WebServiceFeature... features) {
+ return super.getPort(SZRBusinesspartnerTestumgebung, SZR.class, features);
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java
new file mode 100644
index 00000000..6b1b96de
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java
@@ -0,0 +1,503 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import at.asitplus.eidas.specific.core.MsConnectorEventCodes;
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidProcessingService;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.e_government.reference.namespace.persondata._20020228.AlternativeNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import at.gv.egiz.eaaf.core.impl.utils.XPathUtils;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import szrservices.IdentityLinkType;
+import szrservices.PersonInfoType;
+import szrservices.TravelDocumentType;
+
+/**
+ * Task that creates the IdentityLink for an eIDAS authenticated person.
+ *
+ * @author tlenz
+ */
+@Slf4j
+@Component("CreateIdentityLinkTask")
+public class CreateIdentityLinkTask extends AbstractAuthServletTask {
+
+ @Autowired
+ private IConfiguration basicConfig;
+ @Autowired
+ private SzrClient szrClient;
+ @Autowired
+ private ICcSpecificEidProcessingService eidPostProcessor;
+
+ @Autowired
+ private AuthBlockSigningService authBlockSigner;
+
+ private static final String EID_STATUS = "urn:eidgvat:eid.status.eidas";
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.
+ * egovernment.moa.id.process.api.ExecutionContext,
+ * javax.servlet.http.HttpServletRequest,
+ * javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+ try {
+ final AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ final ILightResponse eidasResponse = authProcessData
+ .getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class);
+
+ final Map<String, Object> simpleAttrMap = convertEidasAttrToSimpleMap(
+ eidasResponse.getAttributes().getAttributeMap());
+
+ // post-process eIDAS attributes
+ final ErnbEidData eidData = eidPostProcessor.postProcess(simpleAttrMap);
+
+ // write MDS into technical log and revision log
+ writeMdsLogInformation(eidData);
+
+ //build IdentityLink or VSZ and eidasBind
+ if (basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) {
+ SzrResultHolder idlResult = createDummyIdentityLinkForTestDeployment(eidData);
+ //inject personal-data into session
+ authProcessData.setIdentityLink(idlResult.getIdentityLink());
+
+ // set bPK and bPKType into auth session
+ authProcessData.setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, extendBpkByPrefix(
+ idlResult.getBpK(), pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()));
+ authProcessData.setGenericDataToSession(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME,
+ pendingReq.getServiceProviderConfiguration()
+ .getAreaSpecificTargetIdentifier());
+
+ } else {
+ //build SZR request from eIDAS data
+ final PersonInfoType personInfo = generateSzrRequest(eidData);
+
+ //request SZR based on IDL or E-ID mode
+ if (pendingReq.getServiceProviderConfiguration()
+ .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false)) {
+
+ // get encrypted baseId
+ String vsz = szrClient.getEncryptedStammzahl(personInfo);
+
+ //write revision-Log entry and extended infos personal-identifier mapping
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_VSZ_RECEIVED);
+ writeExtendedRevisionLogEntry(simpleAttrMap, eidData);
+
+
+ // get eIDAS bind
+ String signedEidasBind = szrClient.getEidsaBind(vsz,
+ authBlockSigner.getBase64EncodedPublicKey(),
+ EID_STATUS, eidData);
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_EIDASBIND_RECEIVED);
+ authProcessData.setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, signedEidasBind);
+
+ //get signed AuthBlock
+ String jwsSignature = authBlockSigner.buildSignedAuthBlock(pendingReq);
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.TECH_AUCHBLOCK_CREATED);
+ authProcessData.setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, jwsSignature);
+
+ //inject personal-data into session
+ authProcessData.setEidProcess(true);
+
+ } else {
+ //request SZR
+ SzrResultHolder idlResult = requestSzrForIdentityLink(personInfo);
+
+ //write revision-Log entry for personal-identifier mapping
+ writeExtendedRevisionLogEntry(simpleAttrMap, eidData);
+
+ //check result-data and write revision-log based on current state
+ checkStateAndWriteRevisionLog(idlResult);
+
+ //inject personal-data into session
+ authProcessData.setIdentityLink(idlResult.getIdentityLink());
+ authProcessData.setEidProcess(false);
+
+ // set bPK and bPKType into auth session
+ authProcessData.setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, extendBpkByPrefix(
+ idlResult.getBpK(), pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()));
+ authProcessData.setGenericDataToSession(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME,
+ pendingReq.getServiceProviderConfiguration()
+ .getAreaSpecificTargetIdentifier());
+
+ }
+ }
+
+ //add generic info's into session
+ authProcessData.setForeigner(true);
+ authProcessData.setGenericDataToSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, EidasResponseUtils
+ .parseEidasPersonalIdentifier((String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER))
+ .getFirst());
+ authProcessData.setQaaLevel(eidasResponse.getLevelOfAssurance());
+
+ // store pending-request
+ requestStoreage.storePendingRequest(pendingReq);
+
+
+ } catch (final EidasAttributeException e) {
+ throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e);
+
+ } catch (final EaafException e) {
+ throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e);
+
+ } catch (final Exception e) {
+ log.error("IdentityLink generation for foreign person FAILED.", e);
+ throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e);
+
+ }
+ }
+
+ private void writeExtendedRevisionLogEntry(Map<String, Object> simpleAttrMap, ErnbEidData eidData) {
+ // write ERnB input-data into revision-log
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_REVISIONLOGDATASTORE_ACTIVE, false)) {
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_ERNB_EIDAS_RAW_ID,
+ (String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_ERNB_EIDAS_ERNB_ID, eidData.getPseudonym());
+
+ }
+ }
+
+ private PersonInfoType generateSzrRequest(ErnbEidData eidData) {
+ log.debug("Starting connecting SZR Gateway");
+ final PersonInfoType personInfo = new PersonInfoType();
+ final PersonNameType personName = new PersonNameType();
+ final PhysicalPersonType naturalPerson = new PhysicalPersonType();
+ final TravelDocumentType eDocument = new TravelDocumentType();
+
+ naturalPerson.setName(personName);
+ personInfo.setPerson(naturalPerson);
+ personInfo.setTravelDocument(eDocument);
+
+ // person information
+ personName.setFamilyName(eidData.getFamilyName());
+ personName.setGivenName(eidData.getGivenName());
+ naturalPerson.setDateOfBirth(eidData.getFormatedDateOfBirth());
+ eDocument.setIssuingCountry(eidData.getCitizenCountryCode());
+ eDocument.setDocumentNumber(eidData.getPseudonym());
+
+ // eID document information
+ eDocument.setDocumentType(basicConfig
+ .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE,
+ Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE));
+
+ // set PlaceOfBirth if available
+ if (eidData.getPlaceOfBirth() != null) {
+ log.trace("Find 'PlaceOfBirth' attribute: " + eidData.getPlaceOfBirth());
+ if (basicConfig
+ .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETPLACEOFBIRTHIFAVAILABLE,
+ true)) {
+ naturalPerson.setPlaceOfBirth(eidData.getPlaceOfBirth());
+ log.trace("Adding 'PlaceOfBirth' to ERnB request ... ");
+
+ }
+ }
+
+ // set BirthName if available
+ if (eidData.getBirthName() != null) {
+ log.trace("Find 'BirthName' attribute: " + eidData.getBirthName());
+ if (basicConfig
+ .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETBIRTHNAMEIFAVAILABLE,
+ true)) {
+ final AlternativeNameType alternativeName = new AlternativeNameType();
+ naturalPerson.setAlternativeName(alternativeName);
+ alternativeName.setFamilyName(eidData.getBirthName());
+ log.trace("Adding 'BirthName' to ERnB request ... ");
+
+ }
+ }
+
+ return personInfo;
+
+ }
+
+ private SzrResultHolder requestSzrForIdentityLink(PersonInfoType personInfo)
+ throws SzrCommunicationException, EaafException {
+ //request IdentityLink from SZR
+ final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(personInfo);
+
+ final Element idlFromSzr = (Element) result.getAssertion();
+ IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink();
+
+ // get bPK from SZR
+ String bpk = null;
+ if (basicConfig
+ .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USESRZFORBPKGENERATION, true)) {
+ List<String> bpkList = szrClient
+ .getBpk(personInfo, pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(),
+ basicConfig
+ .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, "no VKZ defined"));
+ if (!bpkList.isEmpty()) {
+ bpk = bpkList.get(0);
+
+ }
+
+
+ } else {
+ log.debug("Calculating bPK from baseId ... ");
+ new BpkBuilder();
+ final Pair<String, String> bpkCalc = BpkBuilder
+ .generateAreaSpecificPersonIdentifier(identityLink.getIdentificationValue(),
+ identityLink.getIdentificationType(),
+ pendingReq.getServiceProviderConfiguration()
+ .getAreaSpecificTargetIdentifier());
+ bpk = bpkCalc.getFirst();
+
+ }
+
+ return new SzrResultHolder(identityLink, bpk);
+
+ }
+
+ private void checkStateAndWriteRevisionLog(SzrResultHolder idlResult) throws SzrCommunicationException {
+ // write some infos into revision log
+ if (idlResult.getIdentityLink() == null) {
+ log.error("ERnB did not return an identity link.");
+ throw new SzrCommunicationException("ernb.00", null);
+
+ }
+ revisionsLogger.logEvent(pendingReq,
+ MsConnectorEventCodes.SZR_IDL_RECEIVED,
+ idlResult.getIdentityLink().getSamlAssertion()
+ .getAttribute(SimpleIdentityLinkAssertionParser.ASSERTIONID));
+
+ if (idlResult.getBpK() == null) {
+ log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration()
+ .getAreaSpecificTargetIdentifier());
+ throw new SzrCommunicationException("ernb.01", null);
+
+ }
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_BPK_RECEIVED);
+ log.debug("ERnB communication was successfull");
+
+ }
+
+ private String extendBpkByPrefix(String bpk, String type) {
+ String bpkType = null;
+
+ if (type.startsWith(EaafConstants.URN_PREFIX_WBPK)) {
+ bpkType = type.substring(EaafConstants.URN_PREFIX_WBPK.length());
+ } else if (type.startsWith(EaafConstants.URN_PREFIX_CDID)) {
+ bpkType = type.substring(EaafConstants.URN_PREFIX_CDID.length());
+ } else if (type.startsWith(EaafConstants.URN_PREFIX_EIDAS)) {
+ bpkType = type.substring(EaafConstants.URN_PREFIX_EIDAS.length());
+ }
+
+ if (bpkType != null) {
+ log.trace("Authenticate user with bPK/wbPK " + bpk + " and Type=" + bpkType);
+ return bpkType + ":" + bpk;
+
+ } else {
+ log.warn("Service Provider Target with: " + type + " is NOT supported. Set bPK as it is ...");
+ return bpk;
+
+ }
+
+ }
+
+ private Map<String, Object> convertEidasAttrToSimpleMap(
+ ImmutableMap<AttributeDefinition<?>, ImmutableSet<? extends AttributeValue<?>>> attributeMap) {
+ final Map<String, Object> result = new HashMap<>();
+
+ for (final AttributeDefinition<?> el : attributeMap.keySet()) {
+
+ final Class<?> parameterizedType = el.getParameterizedType();
+ if (DateTime.class.equals(parameterizedType)) {
+ final DateTime attribute = EidasResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList());
+ if (attribute != null) {
+ result.put(el.getFriendlyName(), attribute);
+ log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + attribute.toString());
+
+ } else {
+ log.info("Ignore empty 'DateTime' attribute");
+ }
+
+ } else if (PostalAddress.class.equals(parameterizedType)) {
+ final PostalAddress addressAttribute = EidasResponseUtils
+ .translateAddressAttribute(el, attributeMap.get(el).asList());
+ if (addressAttribute != null) {
+ result.put(el.getFriendlyName(), addressAttribute);
+ log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + addressAttribute.toString());
+
+ } else {
+ log.info("Ignore empty 'PostalAddress' attribute");
+ }
+
+ } else {
+ final List<String> natPersonIdObj = EidasResponseUtils
+ .translateStringListAttribute(el, attributeMap.get(el));
+ final String stringAttr = natPersonIdObj.get(0);
+ if (StringUtils.isNotEmpty(stringAttr)) {
+ result.put(el.getFriendlyName(), stringAttr);
+ log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + stringAttr);
+
+ } else {
+ log.info("Ignore empty 'String' attribute");
+ }
+
+ }
+ }
+
+ log.debug("Receive #" + result.size() + " attributes with names: " + result.keySet().toString());
+
+ return result;
+ }
+
+ private void writeMdsLogInformation(ErnbEidData eidData) {
+ // log MDS and country code into technical log
+ if (basicConfig
+ .getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_TECHNICALLOG_WRITE_MDS_INTO_TECH_LOG, false)) {
+ log.info("eIDAS Auth. for user: " + eidData.getGivenName() + " " + eidData.getFamilyName() + " " + eidData
+ .getFormatedDateOfBirth() + " " + "from " + eidData.getCitizenCountryCode());
+ }
+
+ // log MDS and country code into revision log
+ if (basicConfig
+ .getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_REVISIONLOG_WRITE_MDS_INTO_REVISION_LOG,
+ false)) {
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.RESPONSE_FROM_EIDAS_MDSDATA,
+ "{" + eidData.getGivenName() + "," + eidData.getFamilyName() + "," + eidData
+ .getFormatedDateOfBirth() + "," + eidData.getCitizenCountryCode() + "}");
+ }
+
+ }
+
+ @Data
+ private static class SzrResultHolder {
+ final IIdentityLink identityLink;
+ final String bpK;
+
+ }
+
+ /**
+ * Build a dummy IdentityLink and a dummy bPK based on eIDAS information.
+ *
+ * <br><br>
+ * <b>FOR LOCAL TESTING ONLY!!!</b>
+ *
+ * @param eidData Information from eIDAS response
+ * @return IdentityLink and bPK
+ * @throws ParserConfigurationException In case of an IDL processing error
+ * @throws SAXException In case of an IDL processing error
+ * @throws IOException In case of an IDL processing error
+ * @throws EaafException In case of a bPK generation error
+ */
+ private SzrResultHolder createDummyIdentityLinkForTestDeployment(ErnbEidData eidData)
+ throws ParserConfigurationException, SAXException, IOException, EaafException {
+ log.warn("SZR-Dummy IS ACTIVE! IdentityLink is NOT VALID!!!!");
+ // create fake IdL
+ // - fetch IdL template from resources
+ final InputStream s = CreateIdentityLinkTask.class
+ .getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml");
+ final Element idlTemplate = DomUtils.parseXmlValidating(s);
+
+ IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
+
+ // replace data
+ final Element idlassertion = identityLink.getSamlAssertion();
+
+ // - set fake baseID;
+ final Node prIdentification = XPathUtils
+ .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+ prIdentification.getFirstChild().setNodeValue(eidData.getPseudonym());
+
+ // - set last name
+ final Node prFamilyName = XPathUtils
+ .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
+ prFamilyName.getFirstChild().setNodeValue(eidData.getFamilyName());
+
+ // - set first name
+ final Node prGivenName = XPathUtils
+ .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
+ prGivenName.getFirstChild().setNodeValue(eidData.getGivenName());
+
+ // - set date of birth
+ final Node prDateOfBirth = XPathUtils
+ .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
+
+ prDateOfBirth.getFirstChild().setNodeValue(eidData.getFormatedDateOfBirth());
+
+ identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink();
+
+ final Pair<String, String> bpkCalc = BpkBuilder
+ .generateAreaSpecificPersonIdentifier(identityLink.getIdentificationValue(),
+ identityLink.getIdentificationType(),
+ pendingReq.getServiceProviderConfiguration()
+ .getAreaSpecificTargetIdentifier());
+ return new SzrResultHolder(identityLink, bpkCalc.getFirst());
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java
new file mode 100644
index 00000000..b43c1bc2
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java
@@ -0,0 +1,255 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
+
+import java.util.UUID;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import at.asitplus.eidas.specific.core.MsConnectorEventCodes;
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.gui.StaticGuiBuilderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidProcessingService;
+import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.auth.commons.tx.BinaryLightToken;
+import eu.eidas.specificcommunication.BinaryLightTokenHelper;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Authentication-process task that generates the Authn. Request to eIDAS Node.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+@Component("ConnecteIDASNodeTask")
+public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
+
+ @Autowired
+ IConfiguration basicConfig;
+ @Autowired
+ ApplicationContext context;
+ @Autowired
+ ITransactionStorage transactionStore;
+ @Autowired
+ ISpringMvcGuiFormBuilder guiBuilder;
+ @Autowired
+ ICcSpecificEidProcessingService ccSpecificProcessing;
+
+ @Override
+ public void execute(ExecutionContext executionContext,
+ HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+
+ try {
+ // get target, environment and validate citizen countryCode
+ final String citizenCountryCode = (String) executionContext.get(
+ MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY);
+ final String environment = (String) executionContext.get(
+ MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT);
+
+ if (StringUtils.isEmpty(citizenCountryCode)) {
+ // illegal state; task should not have been executed without a selected country
+ throw new EidasSAuthenticationException("eidas.03", new Object[] { "" });
+
+ }
+
+ // TODO: maybe add countryCode validation before request ref. impl. eIDAS node
+ log.info("Request eIDAS auth. for citizen of country: " + citizenCountryCode);
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.COUNTRY_SELECTED, citizenCountryCode);
+
+ // build eIDAS AuthnRequest
+ final LightRequest.Builder authnRequestBuilder = LightRequest.builder();
+ authnRequestBuilder.id(UUID.randomUUID().toString());
+
+ // set nameIDFormat
+ authnRequestBuilder.nameIdFormat(
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_EIDAS_NODE_NAMEIDFORMAT));
+
+ // set citizen country code for foreign uses
+ authnRequestBuilder.citizenCountryCode(citizenCountryCode);
+
+ //set Issuer
+ final String issur = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_ENTITYID);
+ if (StringUtils.isEmpty(issur)) {
+ log.error("Found NO 'eIDAS node issuer' in configuration. Authentication NOT possible!");
+ throw new EaafConfigurationException("config.27",
+ new Object[] { "Application config containts NO " + Constants.CONIG_PROPS_EIDAS_NODE_ENTITYID });
+
+ }
+ authnRequestBuilder.issuer(issur);
+
+
+ // Add country-specific informations into eIDAS request
+ ccSpecificProcessing.preProcess(citizenCountryCode, pendingReq, authnRequestBuilder);
+
+ // build request
+ final LightRequest lightAuthnReq = authnRequestBuilder.build();
+
+ // put request into Hazelcast cache
+ final BinaryLightToken token = putRequestInCommunicationCache(lightAuthnReq);
+ final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token);
+
+ // Workaround, because eIDAS node ref. impl. does not return relayState
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER,
+ false)) {
+ log.trace("Put lightRequestId into transactionstore as session-handling backup");
+ transactionStore.put(lightAuthnReq.getId(), pendingReq.getPendingRequestId(), -1);
+
+ }
+
+ // select forward URL regarding the selected environment
+ String forwardUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL);
+ if (StringUtils.isNotEmpty(environment)) {
+ forwardUrl = selectedForwardUrlForEnvironment(environment);
+ }
+
+ if (StringUtils.isEmpty(forwardUrl)) {
+ log.warn("NO ForwardURL defined in configuration. Can NOT forward to eIDAS node! Process stops");
+ throw new EaafConfigurationException("config.08", new Object[] {
+ environment == null ? Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL
+ : Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL + "." + environment
+ });
+
+ }
+ log.debug("ForwardURL: " + forwardUrl + " selected to forward eIDAS request");
+
+ if (basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD,
+ Constants.FORWARD_METHOD_GET).equals(Constants.FORWARD_METHOD_GET)) {
+
+ log.debug("Use http-redirect for eIDAS node forwarding ... ");
+ // send redirect
+ final UriComponentsBuilder redirectUrl = UriComponentsBuilder.fromHttpUrl(forwardUrl);
+ redirectUrl.queryParam(EidasParameterKeys.TOKEN.toString(), tokenBase64);
+ response.sendRedirect(redirectUrl.build().encode().toString());
+
+ } else {
+ log.debug("Use http-post for eIDAS node forwarding ... ");
+ final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration(
+ basicConfig,
+ pendingReq,
+ Constants.TEMPLATE_POST_FORWARD_NAME,
+ null,
+ resourceLoader);
+
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_ENDPOINT, forwardUrl);
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_NAME,
+ EidasParameterKeys.TOKEN.toString());
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_VALUE,
+ tokenBase64);
+
+ guiBuilder.build(request, response, config, "Forward to eIDASNode form");
+
+ }
+
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.EIDAS_NODE_CONNECTED, lightAuthnReq.getId());
+
+ } catch (final EidasSAuthenticationException e) {
+ throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", e);
+
+ } catch (final Exception e) {
+ log.warn("eIDAS AuthnRequest generation FAILED.", e);
+ throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+
+ }
+
+ }
+
+ /**
+ * Select a forward URL from configuration for a specific environment <br>
+ * <br>
+ * <b>Info: </b> This method is needed, because eIDAS Ref. Impl only supports
+ * one countrycode on each instance. In consequence, more than one eIDAS Ref.
+ * Impl nodes are required to support producation, testing, or QS stages for one
+ * country by using one ms-specific eIDAS connector
+ *
+ * @param environment Environment selector from CountrySlection page
+ * @return
+ */
+ private String selectedForwardUrlForEnvironment(String environment) {
+ log.trace("Starting endpoint selection process for environment: " + environment + " ... ");
+ if (environment.equalsIgnoreCase(MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_PRODUCTION)) {
+ return basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL);
+ } else if (environment.equalsIgnoreCase(MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_QS)) {
+ return basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL
+ + "." + MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_QS);
+ } else if (environment.equalsIgnoreCase(
+ MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_TESTING)) {
+ return basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL
+ + "." + MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_TESTING);
+ } else if (environment.equalsIgnoreCase(
+ MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_DEVELOPMENT)) {
+ return basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL
+ + "." + MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_DEVELOPMENT);
+ }
+
+ log.info("Environment selector: " + environment + " is not supported");
+ return null;
+
+ }
+
+ private BinaryLightToken putRequestInCommunicationCache(ILightRequest lightRequest)
+ throws ServletException {
+ final BinaryLightToken binaryLightToken;
+ try {
+ final SpecificCommunicationService springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString());
+
+ binaryLightToken = springManagedSpecificConnectorCommunicationService.putRequest(lightRequest);
+
+ } catch (final SpecificCommunicationException e) {
+ log.error("Unable to process specific request");
+ throw new ServletException(e);
+
+ }
+
+ return binaryLightToken;
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java
new file mode 100644
index 00000000..8d5df99f
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java
@@ -0,0 +1,130 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import at.asitplus.eidas.specific.core.MsConnectorEventCodes;
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.validator.EidasResponseValidator;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import eu.eidas.auth.commons.light.ILightResponse;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component("ReceiveResponseFromeIDASNodeTask")
+public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
+
+ @Autowired
+ private IConfiguration basicConfig;
+ @Autowired
+ private EidasAttributeRegistry attrRegistry;
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) throws TaskExecutionException {
+ try {
+ final ILightResponse eidasResponse = (ILightResponse) request.getAttribute(
+ Constants.DATA_FULL_EIDAS_RESPONSE);
+ if (eidasResponse == null) {
+ log.warn("NO eIDAS response-message found.");
+ throw new EidasSAuthenticationException("eidas.01", null);
+
+ }
+
+ log.debug("Receive eIDAS response with RespId:" + eidasResponse.getId() + " for ReqId:" + eidasResponse
+ .getInResponseToId());
+ log.trace("Full eIDAS-Resp: " + eidasResponse.toString());
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.RESPONSE_FROM_EIDAS_NODE, eidasResponse
+ .getId());
+
+ // check response StatusCode
+ if (!eidasResponse.getStatus().getStatusCode().equals(Constants.SUCCESS_URI)) {
+ log.info("Receice eIDAS Response with StatusCode:" + eidasResponse.getStatus().getStatusCode()
+ + " Subcode:" + eidasResponse.getStatus().getSubStatusCode() + " Msg:" + eidasResponse.getStatus()
+ .getStatusMessage());
+ throw new EidasSAuthenticationException("eidas.02", new Object[] { eidasResponse.getStatus()
+ .getStatusCode(), eidasResponse.getStatus().getStatusMessage() });
+
+ }
+
+ // extract all Attributes from response
+
+ // **********************************************************
+ // ******* MS-specificresponse validation **********
+ // **********************************************************
+ final String spCountry = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE,
+ Constants.DEFAULT_MS_NODE_COUNTRY_CODE);
+ final String citizenCountryCode = (String) executionContext.get(
+ MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY);
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode,
+ attrRegistry);
+
+ // **********************************************************
+ // ******* Store resonse infos into session object **********
+ // **********************************************************
+
+ // update MOA-Session data with received information
+ log.debug("Store eIDAS response information into pending-request.");
+ final EidAuthProcessDataWrapper authProcessData = pendingReq.getSessionData(EidAuthProcessDataWrapper.class);
+ authProcessData.setQaaLevel(eidasResponse.getLevelOfAssurance());
+ authProcessData.setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, eidasResponse);
+
+
+ //inject set flag to inject
+ authProcessData.setTestIdentity(
+ basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_IS_TEST_IDENTITY, false));
+
+ // store MOA-session to database
+ requestStoreage.storePendingRequest(pendingReq);
+
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.RESPONSE_FROM_EIDAS_NODE_VALID);
+
+ } catch (final EaafException e) {
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.RESPONSE_FROM_EIDAS_NODE_NOT_VALID);
+ throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", e);
+
+ } catch (final Exception e) {
+ log.warn("eIDAS Response processing FAILED.", e);
+ revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.RESPONSE_FROM_EIDAS_NODE_NOT_VALID);
+ throw new TaskExecutionException(pendingReq, e.getMessage(),
+ new EidasSAuthenticationException("eidas.05", new Object[] { e.getMessage() }, e));
+
+ }
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java
new file mode 100644
index 00000000..c8c5a069
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java
@@ -0,0 +1,179 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.attribute.AttributeValueMarshaller;
+import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException;
+import eu.eidas.auth.commons.attribute.AttributeValueTransliterator;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+
+public class EidasResponseUtils {
+ private static final Logger log = LoggerFactory.getLogger(EidasResponseUtils.class);
+
+ public static final String PERSONALIDENIFIER_VALIDATION_PATTERN = "^[A-Z,a-z]{2}/[A-Z,a-z]{2}/.*";
+
+ /**
+ * Validate a eIDAS PersonalIdentifier attribute value This validation is done
+ * according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return true if the uniqueID matches to eIDAS to Unique Identifier
+ * specification, otherwise false
+ */
+ public static boolean validateEidasPersonalIdentifier(String uniqueID) {
+ final Pattern pattern = Pattern.compile(PERSONALIDENIFIER_VALIDATION_PATTERN);
+ final Matcher matcher = pattern.matcher(uniqueID);
+ return matcher.matches();
+
+ }
+
+ /**
+ * Parse an eIDAS PersonalIdentifier attribute value into it components. This
+ * processing is done according to eIDAS SAML Attribute Profile - Section 2.2.3
+ * Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return {@link Trible} that contains: <br>
+ * First : citizen country <br>
+ * Second: destination country <br>
+ * Third : unique identifier <br>
+ * or null if the attribute value has a wrong format
+ */
+ public static Triple<String, String, String> parseEidasPersonalIdentifier(String uniqueID) {
+ if (!validateEidasPersonalIdentifier(uniqueID)) {
+ log.error("eIDAS attribute value for {} looks wrong formated. Value: {}",
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER, uniqueID);
+ return null;
+
+ }
+ return Triple.newInstance(uniqueID.substring(0, 2), uniqueID.substring(3, 5), uniqueID.substring(6));
+
+ }
+
+ /**
+ * Get eIDAS attribute-values from eIDAS Node attributes.
+ *
+ * @param attributeDefinition eIDAS attribute definition
+ * @param attributeValues Attributes from eIDAS response
+ * @return Set of attribute values. If more then one value than the first value contains the 'Latin' value.
+ */
+ // TODO: check possible problem with nonLatinCharacters
+ public static List<String> translateStringListAttribute(AttributeDefinition<?> attributeDefinition,
+ ImmutableSet<? extends AttributeValue<?>> attributeValues) {
+ final List<String> stringListAttribute = new ArrayList<>();
+ if (attributeValues != null) {
+ final AttributeValueMarshaller<?> attributeValueMarshaller = attributeDefinition
+ .getAttributeValueMarshaller();
+ for (final AttributeValue<?> attributeValue : attributeValues.asList()) {
+ String valueString = null;
+ try {
+ valueString = attributeValueMarshaller.marshal((AttributeValue) attributeValue);
+
+ log.trace("Find attr: {} with value: {} nonLatinFlag: {} needTransliteration: {}",
+ attributeDefinition.getFriendlyName(), attributeValue.toString(),
+ attributeValue.isNonLatinScriptAlternateVersion(),
+ AttributeValueTransliterator.needsTransliteration(valueString));
+
+ // if (attributeValue.isNonLatinScriptAlternateVersion()) {
+ if (!AttributeValueTransliterator.needsTransliteration(valueString)) {
+ stringListAttribute.add(0, valueString);
+
+ } else {
+ log.trace("Find 'needsTransliteration' flag. Setting this value at last list element ... ");
+ stringListAttribute.add(valueString);
+
+ }
+
+ } catch (final AttributeValueMarshallingException e) {
+ throw new IllegalStateException(e);
+
+ }
+ }
+
+ log.trace("Extract values: {} for attr: {}",
+ StringUtils.join(stringListAttribute, ","), attributeDefinition.getFriendlyName());
+
+ } else {
+ log.info("Can not extract infos from 'null' attribute value");
+
+ }
+
+ return stringListAttribute;
+
+ }
+
+ /**
+ * Convert eIDAS DateTime attribute to Java Object.
+ *
+ * @param attributeDefinition eIDAS attribute definition.
+ * @param attributeValues eIDAS attribute value
+ * @return
+ */
+ @Nullable
+ public static DateTime translateDateAttribute(AttributeDefinition<?> attributeDefinition,
+ ImmutableList<? extends AttributeValue<?>> attributeValues) {
+ if (attributeValues.size() != 0) {
+ final AttributeValue<?> firstAttributeValue = attributeValues.get(0);
+ return (DateTime) firstAttributeValue.getValue();
+
+ }
+
+ return null;
+ }
+
+ /**
+ * Concert eIDAS Address attribute to Java object.
+ *
+ * @param attributeDefinition eIDAS attribute definition
+ * @param attributeValues eIDAS attribute value
+ * @return
+ */
+ @Nullable
+ public static PostalAddress translateAddressAttribute(AttributeDefinition<?> attributeDefinition,
+ ImmutableList<? extends AttributeValue<?>> attributeValues) {
+ final AttributeValue<?> firstAttributeValue = attributeValues.get(0);
+ return (PostalAddress) firstAttributeValue.getValue();
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java
new file mode 100644
index 00000000..e81c4c92
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java
@@ -0,0 +1,305 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.utils;
+
+import at.gv.egiz.eaaf.core.exception.EaafKeyUsageException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.utils.X509Utils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.jose4j.jca.ProviderContext;
+import org.jose4j.jwa.AlgorithmConstraints;
+import org.jose4j.jws.AlgorithmIdentifiers;
+import org.jose4j.jws.JsonWebSignature;
+import org.jose4j.jwx.Headers;
+import org.jose4j.jwx.JsonWebStructure;
+import org.jose4j.keys.resolvers.X509VerificationKeyResolver;
+import org.jose4j.lang.JoseException;
+import org.springframework.util.Base64Utils;
+
+import javax.annotation.Nonnull;
+import java.io.IOException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * {@link JoseUtils} provides static methods JWS and JWE processing.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class JoseUtils {
+
+ /**
+ * Create a JWS signature.
+ *
+ * <p>
+ * Use {@link AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case
+ * of a RSA based key and
+ * {@link AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256}
+ * in case of an ECC based key.
+ * </p>
+ *
+ * @param keyStore KeyStore that should be used
+ * @param keyAlias Alias of the private key
+ * @param keyPassword Password to access the key
+ * @param payLoad PayLoad to sign
+ * @param addFullCertChain If true the full certificate chain will be
+ * added, otherwise only the
+ * X509CertSha256Fingerprint is added into JOSE
+ * header
+ * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging
+ * purposes only
+ * @return Signed PayLoad in serialized form
+ * @throws EaafException In case of a key-access or key-usage error
+ * @throws JoseException In case of a JOSE error
+ */
+ public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore,
+ @Nonnull final String keyAlias, @Nonnull final char[] keyPassword,
+ @Nonnull final String payLoad, boolean addFullCertChain,
+ @Nonnull String friendlyNameForLogging) throws EaafException, JoseException {
+ return createSignature(keyStore, keyAlias, keyPassword, payLoad, addFullCertChain, Collections.emptyMap(),
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA256, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256,
+ friendlyNameForLogging);
+
+ }
+
+ /**
+ * Create a JWS signature.
+ *
+ * <p>
+ * Use {@link AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case
+ * of a RSA based key and
+ * {@link AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256}
+ * in case of an ECC based key.
+ * </p>
+ *
+ * @param keyStore KeyStore that should be used
+ * @param keyAlias Alias of the private key
+ * @param keyPassword Password to access the key
+ * @param payLoad PayLoad to sign
+ * @param addFullCertChain If true the full certificate chain will be
+ * added, otherwise only the
+ * X509CertSha256Fingerprint is added into JOSE
+ * header
+ * @param joseHeaders HeaderName and HeaderValue that should be set
+ * into JOSE header
+ * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging
+ * purposes only
+ * @return Signed PayLoad in serialized form
+ * @throws EaafException In case of a key-access or key-usage error
+ * @throws JoseException In case of a JOSE error
+ */
+ public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore,
+ @Nonnull final String keyAlias, @Nonnull final char[] keyPassword,
+ @Nonnull final String payLoad, boolean addFullCertChain,
+ @Nonnull final Map<String, String> joseHeaders,
+ @Nonnull String friendlyNameForLogging) throws EaafException, JoseException {
+ return createSignature(keyStore, keyAlias, keyPassword, payLoad, addFullCertChain, joseHeaders,
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA256, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256,
+ friendlyNameForLogging);
+
+ }
+
+ /**
+ * Create a JWS signature.
+ *
+ * @param keyStore KeyStore that should be used
+ * @param keyAlias Alias of the private key
+ * @param keyPassword Password to access the key
+ * @param payLoad PayLoad to sign
+ * @param addFullCertChain If true the full certificate chain will be
+ * added, otherwise only the
+ * X509CertSha256Fingerprint is added into JOSE
+ * header
+ * @param joseHeaders HeaderName and HeaderValue that should be set
+ * into JOSE header
+ * @param rsaAlgToUse Signing algorithm that should be used in case
+ * of a signing key based on RSA
+ * @param eccAlgToUse Signing algorithm that should be used in case
+ * of a signing key based on ECC
+ * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging
+ * purposes only
+ * @return Signed PayLoad in serialized form
+ * @throws EaafException In case of a key-access or key-usage error
+ * @throws JoseException In case of a JOSE error
+ */
+ public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore,
+ @Nonnull final String keyAlias, @Nonnull final char[] keyPassword,
+ @Nonnull final String payLoad, boolean addFullCertChain,
+ @Nonnull final Map<String, String> joseHeaders,
+ @Nonnull final String rsaAlgToUse, @Nonnull final String eccAlgToUse,
+ @Nonnull String friendlyNameForLogging) throws EaafException, JoseException {
+
+ final JsonWebSignature jws = new JsonWebSignature();
+
+ // set payload
+ jws.setPayload(payLoad);
+
+ // set JOSE headers
+ for (final Entry<String, String> el : joseHeaders.entrySet()) {
+ log.trace("Set JOSE header: {} with value: {} into JWS", el.getKey(), el.getValue());
+ jws.setHeader(el.getKey(), el.getValue());
+
+ }
+
+ // set signing information
+ final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
+ keyStore.getFirst(), keyAlias, keyPassword, true, friendlyNameForLogging);
+ jws.setKey(signingCred.getFirst());
+ jws.setAlgorithmHeaderValue(getKeyOperationAlgorithmFromCredential(
+ jws.getKey(), rsaAlgToUse, eccAlgToUse, friendlyNameForLogging));
+
+ // 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();
+
+ }
+
+ /**
+ * Verify a JOSE signature.
+ *
+ * @param serializedContent Serialized content that should be verified
+ * @param trustedCerts Trusted certificates that should be used for
+ * verification
+ * @param constraints {@link AlgorithmConstraints} for verification
+ * @return {@link JwsResult} object
+ * @throws JoseException In case of a signature verification error
+ * @throws IOException In case of a general error
+ */
+ public static JwsResult 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.");
+ if (log.isDebugEnabled()) {
+ try {
+ log.debug("Cert: {}", Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded()));
+
+ } catch (final CertificateEncodingException e) {
+ log.warn("Can not create DEBUG output", e);
+
+ }
+ }
+ }
+
+ } 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 JwsResult(
+ jws.verifySignature(),
+ jws.getUnverifiedPayload(),
+ jws.getHeaders(),
+ x5cCerts);
+
+ }
+
+ /**
+ * Select signature algorithm for a given credential.
+ *
+ * @param key {@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
+ * @param friendlyNameForLogging KeyStore friendlyName for logging purposes
+ * @return either the RSA based algorithm or the EC based algorithm
+ * @throws EaafKeyUsageException In case of an unsupported private-key type
+ */
+ private static String getKeyOperationAlgorithmFromCredential(Key key,
+ String rsaSigAlgorithm, String ecSigAlgorithm, String friendlyNameForLogging)
+ throws EaafKeyUsageException {
+ if (key instanceof RSAPrivateKey) {
+ return rsaSigAlgorithm;
+
+ } else if (key instanceof ECPrivateKey) {
+ return ecSigAlgorithm;
+
+ } else {
+ log.warn("Could NOT select the cryptographic algorithm from Private-Key type");
+ throw new EaafKeyUsageException(EaafKeyUsageException.ERROR_CODE_01,
+ friendlyNameForLogging,
+ "Can not select cryptographic algorithm");
+
+ }
+
+ }
+
+ private JoseUtils() {
+
+ }
+
+ @Getter
+ @AllArgsConstructor
+ public static class JwsResult {
+ final boolean valid;
+ final String payLoad;
+ final Headers fullJoseHeader;
+ final List<X509Certificate> x5cCerts;
+
+ }
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/LoggingHandler.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/LoggingHandler.java
new file mode 100644
index 00000000..70290cd3
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/LoggingHandler.java
@@ -0,0 +1,72 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LoggingHandler implements SOAPHandler<SOAPMessageContext> {
+
+ Logger log = LoggerFactory.getLogger(LoggingHandler.class);
+
+ @Override
+ public boolean handleMessage(SOAPMessageContext context) {
+ final SOAPMessage msg = context.getMessage();
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ try {
+ msg.writeTo(bos);
+ log.trace(bos.toString("UTF-8"));
+ log.trace(new String(bos.toByteArray(), "UTF-8"));
+
+ } catch (final Exception e) {
+ log.trace(e.getMessage(), e);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean handleFault(SOAPMessageContext context) {
+ return handleMessage(context);
+ }
+
+ @Override
+ public void close(MessageContext context) {
+ }
+
+ @Override
+ public Set<QName> getHeaders() {
+ return null;
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/validator/EidasResponseValidator.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/validator/EidasResponseValidator.java
new file mode 100644
index 00000000..9d9a0647
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/validator/EidasResponseValidator.java
@@ -0,0 +1,175 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.validator;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableSet;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasValidationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
+
+/**
+ * eIDAS Response validator implementation.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasResponseValidator {
+ private static final Logger log = LoggerFactory.getLogger(EidasResponseValidator.class);
+
+ /**
+ * Validate an eIDAS Response according to internal state.
+ *
+ * @param pendingReq Current pending request
+ * @param eidasResponse eIDAS response object
+ * @param spCountry Country-Code of the Service Provider
+ * @param citizenCountryCode Country-Code of the Citizen
+ * @param attrRegistry eIDAS Attribute registry implementation
+ * @throws EidasValidationException In case of an validation error
+ */
+ public static void validateResponse(IRequest pendingReq, ILightResponse eidasResponse, String spCountry,
+ String citizenCountryCode, EidasAttributeRegistry attrRegistry) throws EidasValidationException {
+
+ /*-----------------------------------------------------|
+ * validate received LoA against minimum required LoA |
+ *_____________________________________________________|
+ */
+ final LevelOfAssurance respLoA = LevelOfAssurance.fromString(eidasResponse.getLevelOfAssurance());
+ final List<String> allowedLoAs = pendingReq.getServiceProviderConfiguration().getRequiredLoA();
+ boolean loaValid = false;
+ for (final String allowedLoaString : allowedLoAs) {
+ final LevelOfAssurance allowedLoa = LevelOfAssurance.fromString(allowedLoaString);
+ if (respLoA.numericValue() >= allowedLoa.numericValue()) {
+ log.debug("Response contains valid LoA. Resume process ... ");
+ loaValid = true;
+ break;
+
+ } else {
+ log.trace("Allowed LoA: " + allowedLoaString + " DOES NOT match response LoA: " + eidasResponse
+ .getLevelOfAssurance());
+ }
+
+ }
+
+ if (!loaValid) {
+ log.error("eIDAS Response LevelOfAssurance is lower than the required! "
+ + "(Resp-LoA:{} Req-LoA:{} )", respLoA.getValue(), allowedLoAs.toArray());
+ throw new EidasValidationException("eidas.06", new Object[] { respLoA.getValue() });
+
+ }
+
+ /*-----------------------------------------------------|
+ * validate 'PersonalIdentifier' attribute |
+ *_____________________________________________________|
+ */
+ final AttributeDefinition<?> attrDefinition = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final ImmutableSet<? extends AttributeValue<?>> attributeValues = eidasResponse.getAttributes()
+ .getAttributeMap().get(attrDefinition);
+ final List<String> personalIdObj = EidasResponseUtils.translateStringListAttribute(attrDefinition,
+ attributeValues);
+
+ // check if attribute exists
+ if (personalIdObj == null || personalIdObj.isEmpty()) {
+ log.warn("eIDAS Response include NO 'PersonalIdentifier' attriubte "
+ + ".... That can be a BIG problem in further processing steps");
+ throw new EidasValidationException("eidas.05", new Object[] { "NO 'PersonalIdentifier' attriubte" });
+
+ } else if (personalIdObj.size() > 1) {
+ log.warn("eIDAS Response include MORE THAN ONE 'PersonalIdentifier' attriubtes "
+ + ".... That can be a BIG problem in further processing steps");
+ throw new EidasValidationException("eidas.05", new Object[] {
+ "MORE THAN ONE 'PersonalIdentifier' attriubtes" });
+
+ } else {
+ final String natPersId = personalIdObj.get(0);
+ // validate attribute value format
+ final Triple<String, String, String> split =
+ EidasResponseUtils.parseEidasPersonalIdentifier(natPersId);
+ if (split == null) {
+ throw new EidasValidationException("eidas.07",
+ new Object[] {
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Wrong identifier format" });
+
+ } else {
+ // validation according to eIDAS SAML Attribute Profile, Section 2.2.3
+ if (StringUtils.isEmpty(split.getSecond())) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO destination country. Value:" + natPersId);
+ throw new EidasValidationException("eidas.07",
+ new Object[] {
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty destination country" });
+
+ }
+ if (!split.getSecond().equalsIgnoreCase(spCountry)) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes wrong destination country. Value:" + natPersId
+ + " SP-Country:" + spCountry);
+ throw new EidasValidationException("eidas.07",
+ new Object[] {
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Destination country does not match to SP country" });
+
+ }
+
+ if (StringUtils.isEmpty(split.getFirst())) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO citizen country. Value:" + natPersId);
+ throw new EidasValidationException("eidas.07",
+ new Object[] {
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty citizen country" });
+
+ }
+ if (!split.getFirst().equalsIgnoreCase(citizenCountryCode)) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes a citizen country that does not match to service-provider country. "
+ + " Value:" + natPersId
+ + " citiczen Country:" + spCountry);
+ throw new EidasValidationException("eidas.07",
+ new Object[] {
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Citizen country does not match to eIDAS-node country that generates the response" });
+
+ }
+ }
+ }
+
+ }
+}
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
new file mode 100644
index 00000000..a8d2991d
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -0,0 +1 @@
+at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasAuthenticationSpringResourceProvider \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml
new file mode 100644
index 00000000..55bb1ace
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pd:ProcessDefinition id="eIDASAuthentication_v2"
+ xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1">
+
+
+ <pd:Task id="createAuthnRequest" class="ConnecteIDASNodeTask" />
+ <pd:Task id="receiveAuthnResponse"
+ class="ReceiveResponseFromeIDASNodeTask" async="true" />
+ <pd:Task id="finalizeAuthentication"
+ class="FinalizeAuthenticationTask" />
+ <pd:Task id="generateIdentityLink"
+ class="CreateIdentityLinkTask" />
+
+ <pd:StartEvent id="start" />
+
+ <pd:Transition from="start"
+ to="createAuthnRequest" />
+ <pd:Transition from="createAuthnRequest"
+ to="receiveAuthnResponse" />
+ <pd:Transition from="receiveAuthnResponse"
+ to="generateIdentityLink" />
+ <pd:Transition from="generateIdentityLink"
+ to="finalizeAuthentication" />
+ <pd:Transition from="finalizeAuthentication"
+ to="end" />
+
+ <pd:EndEvent id="end" />
+
+</pd:ProcessDefinition>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/additional-attributes.xml b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/additional-attributes.xml
new file mode 100644
index 00000000..a72ac1e8
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/additional-attributes.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2017 by European Commission
+ ~
+ ~ 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/page/eupl-text-11-12
+ ~
+ ~ 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.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>Dynamic attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/AdditionalAttribute</entry>
+ <entry key="1.FriendlyName">AdditionalAttribute</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">false</entry>
+ <entry key="1.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="1.XmlType.LocalPart">string</entry>
+ <entry key="1.XmlType.NamespacePrefix">xs</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalAdditionalAttribute</entry>
+ <entry key="2.FriendlyName">LegalAdditionalAttribute</entry>
+ <entry key="2.PersonType">LegalPerson</entry>
+ <entry key="2.Required">false</entry>
+ <entry key="2.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="2.XmlType.LocalPart">string</entry>
+ <entry key="2.XmlType.NamespacePrefix">xs</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+</properties>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/eidas-attributes.xml b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/eidas-attributes.xml
new file mode 100644
index 00000000..c9288d59
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS/eidas-attributes.xml
@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2017 by European Commission
+ ~
+ ~ 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/page/eupl-text-11-12
+ ~
+ ~ 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.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>eIDAS attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier</entry>
+ <entry key="1.FriendlyName">PersonIdentifier</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">true</entry>
+ <entry key="1.UniqueIdentifier">true</entry>
+ <entry key="1.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="1.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="1.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</entry>
+ <entry key="2.FriendlyName">FamilyName</entry>
+ <entry key="2.PersonType">NaturalPerson</entry>
+ <entry key="2.Required">true</entry>
+ <entry key="2.TransliterationMandatory">true</entry>
+ <entry key="2.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="2.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="2.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="3.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</entry>
+ <entry key="3.FriendlyName">FirstName</entry>
+ <entry key="3.PersonType">NaturalPerson</entry>
+ <entry key="3.Required">true</entry>
+ <entry key="3.TransliterationMandatory">true</entry>
+ <entry key="3.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="3.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="3.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="3.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="4.NameUri">http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</entry>
+ <entry key="4.FriendlyName">DateOfBirth</entry>
+ <entry key="4.PersonType">NaturalPerson</entry>
+ <entry key="4.Required">true</entry>
+ <entry key="4.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="4.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="4.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="4.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="5.NameUri">http://eidas.europa.eu/attributes/naturalperson/BirthName</entry>
+ <entry key="5.FriendlyName">BirthName</entry>
+ <entry key="5.PersonType">NaturalPerson</entry>
+ <entry key="5.Required">false</entry>
+ <entry key="5.TransliterationMandatory">true</entry>
+ <entry key="5.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="5.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="5.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="5.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="6.NameUri">http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth</entry>
+ <entry key="6.FriendlyName">PlaceOfBirth</entry>
+ <entry key="6.PersonType">NaturalPerson</entry>
+ <entry key="6.Required">false</entry>
+ <entry key="6.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="6.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="6.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="6.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="7.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentAddress</entry>
+ <entry key="7.FriendlyName">CurrentAddress</entry>
+ <entry key="7.PersonType">NaturalPerson</entry>
+ <entry key="7.Required">false</entry>
+ <entry key="7.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="7.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="7.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="7.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.CurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="8.NameUri">http://eidas.europa.eu/attributes/naturalperson/Gender</entry>
+ <entry key="8.FriendlyName">Gender</entry>
+ <entry key="8.PersonType">NaturalPerson</entry>
+ <entry key="8.Required">false</entry>
+ <entry key="8.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="8.XmlType.LocalPart">GenderType</entry>
+ <entry key="8.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="8.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="9.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier</entry>
+ <entry key="9.FriendlyName">LegalPersonIdentifier</entry>
+ <entry key="9.PersonType">LegalPerson</entry>
+ <entry key="9.Required">true</entry>
+ <entry key="9.UniqueIdentifier">true</entry>
+ <entry key="9.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="9.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="9.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="9.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="10.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalName</entry>
+ <entry key="10.FriendlyName">LegalName</entry>
+ <entry key="10.PersonType">LegalPerson</entry>
+ <entry key="10.Required">true</entry>
+ <entry key="10.TransliterationMandatory">true</entry>
+ <entry key="10.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="10.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="10.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="10.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="11.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonAddress</entry>
+ <entry key="11.FriendlyName">LegalAddress</entry>
+ <entry key="11.PersonType">LegalPerson</entry>
+ <entry key="11.Required">false</entry>
+ <entry key="11.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="11.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="11.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="11.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.LegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="12.NameUri">http://eidas.europa.eu/attributes/legalperson/VATRegistrationNumber</entry>
+ <entry key="12.FriendlyName">VATRegistration</entry>
+ <entry key="12.PersonType">LegalPerson</entry>
+ <entry key="12.Required">false</entry>
+ <entry key="12.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="12.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="12.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="12.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="13.NameUri">http://eidas.europa.eu/attributes/legalperson/TaxReference</entry>
+ <entry key="13.FriendlyName">TaxReference</entry>
+ <entry key="13.PersonType">LegalPerson</entry>
+ <entry key="13.Required">false</entry>
+ <entry key="13.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="13.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="13.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="13.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="14.NameUri">http://eidas.europa.eu/attributes/legalperson/D-2012-17-EUIdentifier</entry>
+ <entry key="14.FriendlyName">D-2012-17-EUIdentifier</entry>
+ <entry key="14.PersonType">LegalPerson</entry>
+ <entry key="14.Required">false</entry>
+ <entry key="14.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="14.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="14.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="14.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="15.NameUri">http://eidas.europa.eu/attributes/legalperson/LEI</entry>
+ <entry key="15.FriendlyName">LEI</entry>
+ <entry key="15.PersonType">LegalPerson</entry>
+ <entry key="15.Required">false</entry>
+ <entry key="15.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="15.XmlType.LocalPart">LEIType</entry>
+ <entry key="15.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="15.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="16.NameUri">http://eidas.europa.eu/attributes/legalperson/EORI</entry>
+ <entry key="16.FriendlyName">EORI</entry>
+ <entry key="16.PersonType">LegalPerson</entry>
+ <entry key="16.Required">false</entry>
+ <entry key="16.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="16.XmlType.LocalPart">EORIType</entry>
+ <entry key="16.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="16.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="17.NameUri">http://eidas.europa.eu/attributes/legalperson/SEED</entry>
+ <entry key="17.FriendlyName">SEED</entry>
+ <entry key="17.PersonType">LegalPerson</entry>
+ <entry key="17.Required">false</entry>
+ <entry key="17.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="17.XmlType.LocalPart">SEEDType</entry>
+ <entry key="17.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="17.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="18.NameUri">http://eidas.europa.eu/attributes/legalperson/SIC</entry>
+ <entry key="18.FriendlyName">SIC</entry>
+ <entry key="18.PersonType">LegalPerson</entry>
+ <entry key="18.Required">false</entry>
+ <entry key="18.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="18.XmlType.LocalPart">SICType</entry>
+ <entry key="18.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="18.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="19.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PersonIdentifier</entry>
+ <entry key="19.FriendlyName">RepresentativePersonIdentifier</entry>
+ <entry key="19.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="19.Required">false</entry>
+ <entry key="19.UniqueIdentifier">true</entry>
+ <entry key="19.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="19.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="19.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="19.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="20.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentFamilyName</entry>
+ <entry key="20.FriendlyName">RepresentativeFamilyName</entry>
+ <entry key="20.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="20.Required">false</entry>
+ <entry key="20.TransliterationMandatory">true</entry>
+ <entry key="20.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="20.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="20.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="20.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="21.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentGivenName</entry>
+ <entry key="21.FriendlyName">RepresentativeFirstName</entry>
+ <entry key="21.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="21.Required">false</entry>
+ <entry key="21.TransliterationMandatory">true</entry>
+ <entry key="21.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="21.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="21.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="21.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="22.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/DateOfBirth</entry>
+ <entry key="22.FriendlyName">RepresentativeDateOfBirth</entry>
+ <entry key="22.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="22.Required">false</entry>
+ <entry key="22.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="22.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="22.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="22.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="23.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/BirthName</entry>
+ <entry key="23.FriendlyName">RepresentativeBirthName</entry>
+ <entry key="23.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="23.Required">false</entry>
+ <entry key="23.TransliterationMandatory">true</entry>
+ <entry key="23.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="23.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="23.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="23.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="24.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PlaceOfBirth</entry>
+ <entry key="24.FriendlyName">RepresentativePlaceOfBirth</entry>
+ <entry key="24.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="24.Required">false</entry>
+ <entry key="24.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="24.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="24.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="24.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="25.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentAddress</entry>
+ <entry key="25.FriendlyName">RepresentativeCurrentAddress</entry>
+ <entry key="25.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="25.Required">false</entry>
+ <entry key="25.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="25.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="25.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="25.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvCurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="26.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/Gender</entry>
+ <entry key="26.FriendlyName">RepresentativeGender</entry>
+ <entry key="26.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="26.Required">false</entry>
+ <entry key="26.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="26.XmlType.LocalPart">GenderType</entry>
+ <entry key="26.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="26.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="27.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonIdentifier</entry>
+ <entry key="27.FriendlyName">RepresentativeLegalPersonIdentifier</entry>
+ <entry key="27.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="27.Required">false</entry>
+ <entry key="27.UniqueIdentifier">true</entry>
+ <entry key="27.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="27.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="27.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="27.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="28.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalName</entry>
+ <entry key="28.FriendlyName">RepresentativeLegalName</entry>
+ <entry key="28.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="28.Required">false</entry>
+ <entry key="28.TransliterationMandatory">true</entry>
+ <entry key="28.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="28.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="28.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="28.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="29.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="29.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="29.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="29.Required">false</entry>
+ <entry key="29.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="29.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="29.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="29.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="30.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="30.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="30.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="30.Required">false</entry>
+ <entry key="30.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="30.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="30.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="30.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="31.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/TaxReference</entry>
+ <entry key="31.FriendlyName">RepresentativeTaxReference</entry>
+ <entry key="31.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="31.Required">false</entry>
+ <entry key="31.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="31.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="31.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="31.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="32.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/D-2012-17-EUIdentifier</entry>
+ <entry key="32.FriendlyName">RepresentativeD-2012-17-EUIdentifier</entry>
+ <entry key="32.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="32.Required">false</entry>
+ <entry key="32.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="32.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="32.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="32.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="33.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LEI</entry>
+ <entry key="33.FriendlyName">RepresentativeLEI</entry>
+ <entry key="33.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="33.Required">false</entry>
+ <entry key="33.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="33.XmlType.LocalPart">LEIType</entry>
+ <entry key="33.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="33.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="34.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/EORI</entry>
+ <entry key="34.FriendlyName">RepresentativeEORI</entry>
+ <entry key="34.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="34.Required">false</entry>
+ <entry key="34.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="34.XmlType.LocalPart">EORIType</entry>
+ <entry key="34.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="34.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="35.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SEED</entry>
+ <entry key="35.FriendlyName">RepresentativeSEED</entry>
+ <entry key="35.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="35.Required">false</entry>
+ <entry key="35.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="35.XmlType.LocalPart">SEEDType</entry>
+ <entry key="35.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="35.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="36.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SIC</entry>
+ <entry key="36.FriendlyName">RepresentativeSIC</entry>
+ <entry key="36.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="36.Required">false</entry>
+ <entry key="36.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="36.XmlType.LocalPart">SICType</entry>
+ <entry key="36.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="36.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="39.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="39.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="39.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="39.Required">false</entry>
+ <entry key="39.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="39.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="39.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="39.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="40.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="40.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="40.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="40.Required">false</entry>
+ <entry key="40.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="40.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="40.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="40.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+
+</properties>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml b/modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml
new file mode 100644
index 00000000..f37516f8
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml
@@ -0,0 +1,100 @@
+<?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 />
+
+ <import
+ resource="classpath:specificCommunicationDefinitionApplicationContext.xml" />
+
+ <bean id="SZRClientForeIDAS"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient" />
+
+ <bean id="specificConnectorAttributesFile"
+ class="java.lang.String">
+ <constructor-arg value="eidas-attributes.xml" />
+ </bean>
+
+ <bean id="specificAdditionalAttributesFile"
+ class="java.lang.String">
+ <constructor-arg value="additional-attributes.xml" />
+ </bean>
+
+ <bean id="specificConnectorAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="#{specificConnectorConfigRepository}#{specificConnectorAttributesFile}" />
+ </bean>
+
+ <bean id="specificConnectorAdditionalAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="#{specificConnectorConfigRepository}#{specificAdditionalAttributesFile}" />
+ </bean>
+
+ <bean id="eIDASAuthModule"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasAuthenticationModulImpl">
+ <property name="priority" value="2" />
+ </bean>
+
+ <bean id="eIDASSignalServlet"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet" />
+
+ <bean id="attributeRegistry"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry">
+ <property name="eidasAttributesFile"
+ ref="specificConnectorAttributesFileWithPath" />
+ <property name="additionalAttributesFile"
+ ref="specificConnectorAdditionalAttributesFileWithPath" />
+ </bean>
+
+ <!-- <bean id="eIDASDataStore" class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.eIDASDataStore"
+ /> -->
+
+ <bean id="authBlockSigningService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService" />
+
+ <bean id="EIDPostProcessingService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.CcSpecificEidProcessingService" />
+
+ <bean id="DE-Processor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeEidProcessor">
+ <property name="priority" value="1" />
+ </bean>
+
+ <bean id="LU-Processor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.LuEidProcessor">
+ <property name="priority" value="1" />
+ </bean>
+
+ <bean id="NL-Processor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.NlEidProcessor">
+ <property name="priority" value="1" />
+ </bean>
+
+ <bean id="Default-Processor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.GenericEidProcessor">
+ <property name="priority" value="0" />
+ </bean>
+
+ <!-- Authentication Process Tasks -->
+ <bean id="ConnecteIDASNodeTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateAuthnRequestTask"
+ scope="prototype" />
+
+ <bean id="ReceiveResponseFromeIDASNodeTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAuthnResponseTask"
+ scope="prototype" />
+
+ <bean id="CreateIdentityLinkTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask"
+ scope="prototype" />
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml b/modules/authmodule-eIDAS-v2/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml
new file mode 100644
index 00000000..91b8e5e4
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml:Assertion
+ xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
+ xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#"
+ xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#"
+ xmlns:si="http://www.w3.org/2001/XMLSchema-instance"
+ AssertionID="szr.bmi.gv.at-AssertionID13456264458587874"
+ IssueInstant="2012-08-22T11:07:25+01:00"
+ Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1"
+ MinorVersion="0" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <saml:AttributeStatement>
+ <saml:Subject>
+ <saml:SubjectConfirmation>
+ <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches
+ </saml:ConfirmationMethod>
+ <saml:SubjectConfirmationData>
+ <pr:Person si:type="pr:PhysicalPersonType">
+ <pr:Identification>
+ <pr:Value>wJO/bvDJjUysG0yARn7I6w==</pr:Value>
+ <pr:Type>urn:publicid:gv.at:baseid</pr:Type>
+ </pr:Identification>
+ <pr:Name>
+ <pr:GivenName>XXXRúùd</pr:GivenName>
+ <pr:FamilyName primary="undefined">XXXVàn Nisteĺrooy
+ </pr:FamilyName>
+ </pr:Name>
+ <pr:DateOfBirth>1969-02-13</pr:DateOfBirth>
+ </pr:Person>
+ </saml:SubjectConfirmationData>
+ </saml:SubjectConfirmation>
+ </saml:Subject>
+ <saml:Attribute AttributeName="CitizenPublicKey"
+ AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2">
+ <saml:AttributeValue>
+ <ecdsa:ECDSAKeyValue>
+ <ecdsa:DomainParameters>
+ <ecdsa:NamedCurve
+ URN="urn:oid:1.2.840.10045.3.1.7" />
+ </ecdsa:DomainParameters>
+ <ecdsa:PublicKey>
+ <ecdsa:X
+ Value="22280299907126338788314199678167217078072953115254374209747379168424021905237"
+ si:type="ecdsa:PrimeFieldElemType" />
+ <ecdsa:Y
+ Value="40387096985250872237992703378062984723606079359080588656963239072881568409170"
+ si:type="ecdsa:PrimeFieldElemType" />
+ </ecdsa:PublicKey>
+ </ecdsa:ECDSAKeyValue>
+ </saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute AttributeName="CitizenPublicKey"
+ AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2">
+ <saml:AttributeValue>
+ <dsig:RSAKeyValue>
+ <dsig:Modulus>4Y4FL09VhczsfYQgFPuycP8quJNZBAAu1R1rFXNodI2711B6BTMjAGQn6xuFWfd3/nyFav/MLTr/
+ t2VazvANS4TRFxJAcWyIx7xbxCdzZr6gJ+FCmq4g5JPrQvt50v3JX+wKSYft1gHBOWlDn90Ia4Gm
+ P8MVuze21T+VVKM6ZklmS6d5PT1er/uYQFydGErmJ17xlSQG6Fi5xuftopBDyJxG1tL1KIebpLFg
+ gaM2EyuB1HxH8/+Mfqa4UgeqIH65
+ </dsig:Modulus>
+ <dsig:Exponent>AQAB</dsig:Exponent>
+ </dsig:RSAKeyValue>
+ </saml:AttributeValue>
+ </saml:Attribute>
+ </saml:AttributeStatement>
+ <dsig:Signature>
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod
+ Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+ <dsig:SignatureMethod
+ Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform
+ Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath>not(ancestor-or-self::pr:Identification)
+ </dsig:XPath>
+ </dsig:Transform>
+ <dsig:Transform
+ Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
+ </dsig:Transforms>
+ <dsig:DigestMethod
+ Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>KEQEPY2O3Z3IRaISSSoRZVPzsHE=
+ </dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference
+ Type="http://www.w3.org/2000/09/xmldsig#Manifest"
+ URI="#manifest">
+ <dsig:DigestMethod
+ Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>gzGhjH1kdmPcPbgen0xojNIoJLk=
+ </dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue>
+ 06wqWHgplwpu3N5HMhzb6QC5NkXMO1z4N4oc1L6eDqwZlvFJ9X1XGW//QqviKO9oog3il7IzdfJwnjygR4trgGCIqx+JYCDHJCrG9l8zlxlSW0ZqfsygGXthutcQ1aeUpfO6jYuhnWOUywa8BgzukRtWT+AOJBQZPRYTb8IBmey+uAwlhFLni94eMOd81l+efCvkWi3jRajwsG8ZOaNxSZT3aEV5vj+32Aqtx2MPEVzQWtIA7GqZi+EzcdSdHQvHhg7UB+8kqbU70ENAJbEMTANFZYvLOJ0Om9KfDtPf/+R2TvTc360fNo9RnPl04pHPhCIjcGZhFZorBpUhXFwd2Q==
+ </dsig:SignatureValue>
+ <dsig:KeyInfo>
+ <dsig:X509Data>
+ <dsig:X509Certificate>MIIF3TCCBMWgAwIBAgIDByniMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMB4XDTEwMDcyODExMzY0M1oXDTE1MDcyODExMzY0M1owgbYxCzAJBgNVBAYTAkFUMR4wHAYDVQQKDBVEYXRlbnNjaHV0emtvbW1pc3Npb24xIjAgBgNVBAsMGVN0YW1temFobHJlZ2lzdGVyYmVob2VyZGUxLjAsBgNVBAMMJVNpZ25hdHVyc2VydmljZSBEYXRlbnNjaHV0emtvbW1pc3Npb24xFTATBgNVBAUTDDMyNTkyODMyMzk5ODEcMBoGCSqGSIb3DQEJARYNZHNrQGRzay5ndi5hdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+dBSEBGj2jUXIK1Mp3lVxc/Za+pJMiyKrX3G1ZxgX/ikx7D9scsPYMt473LlAWl9cmCbHbJK+PV2XNNdURLMUCIX+4vUNs2MHeDTQtX8BXjJFpwJYSoaRJQ39FVS/1r5sWcra9Hhdm7w5Gtx/2ukyDX0kdkxawkhP4EQEzi/SI+Fugn+WqgQ1nAdlbxb/dcBw5w1h9b3lmuwUf4z3ooQWUD2DgA/kKd1KejNR43mLUsmvSzevPxT9zs78pOR1OacB7IszTVJPXeOEaaNZHnnB/UeO3g8LEV/3OkXcUgcMkbIIiaBHlll71Pq0COj9kqjXoe7OrRjLY5i3KwOpa6TMCAwEAAaOCAgcwggIDMBMGA1UdIwQMMAqACEkcWDpP6A0DMH8GCCsGAQUFBwEBBHMwcTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuYS10cnVzdC5hdC9vY3NwMEYGCCsGAQUFBzAChjpodHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMmEuY3J0MFQGA1UdIARNMEswSQYGKigAEQESMD8wPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cuYS10cnVzdC5hdC9kb2NzL2NwL2Etc2lnbi1BbXRzc2lnbmF0dXIwgZ4GA1UdHwSBljCBkzCBkKCBjaCBioaBh2xkYXA6Ly9sZGFwLmEtdHJ1c3QuYXQvb3U9YS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMixvPUEtVHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQITAgOnhr0tbowDgYDVR0PAQH/BAQDAgSwMCAGA1UdEQQZMBeBFW1hcmN1cy5oaWxkQGRzay5ndi5hdDAJBgNVHRMEAjAAMA4GByooAAoBBwEEAwEB/zAUBgcqKAAKAQEBBAkMB0JTQi1EU0swDQYJKoZIhvcNAQEFBQADggEBAHTklnvPCH/bJSOlIPbLUEkSGuFHsektSZ8Vr22x/Yv7EzsxoQrJIiz2mQ2gQqFuExdWYxvsowjiSbiis9iUf1c0zscvDS3mIZxGs4M89XHsjHnIyb+Fuwnamw65QrFvM1tNB1ZMjxJ3x+YmHLHdtT3BEBcr3/NCRHd2S0HoBspNz9HVgJaZY1llR7poKBvnAc4g1i+QTvyVb00PtKxR9Lw/9ABInX/1pzpxqrPy7Ib2OP8z6dd3WHmIsCiSHUaj0Dxwwln6fYJjhxZ141SnbovlCLYtrsZLXoi9ljIqX4xO0PwMI2RfNc9cXxTRrRS6rEOvX7PpvgXiDXhp592Yyp4=
+ </dsig:X509Certificate>
+ </dsig:X509Data>
+ </dsig:KeyInfo>
+ <dsig:Object>
+ <dsig:Manifest Id="manifest">
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform
+ Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath>not(ancestor-or-self::dsig:Signature)
+ </dsig:XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod
+ Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+ <dsig:DigestValue>8e7RjLnA4Mgltq5ruIJzheKGxu0=
+ </dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:Manifest>
+ </dsig:Object>
+ </dsig:Signature>
+</saml:Assertion> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.1.WSDL b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.1.WSDL
new file mode 100644
index 00000000..3c34458d
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.1.WSDL
@@ -0,0 +1,939 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions targetNamespace="urn:SZRServices" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:pvp="http://egov.gv.at/pvp1.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:szr="urn:SZRServices" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <types>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://reference.e-government.gv.at/namespace/persondata/20020228#">
+ <xs:complexType name="PhysicalPersonType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Identification" type="pd:IdentificationType" />
+ <xs:element minOccurs="1" name="Name" type="pd:PersonNameType" />
+ <xs:element minOccurs="0" name="AlternativeName" type="pd:AlternativeNameType" />
+ <xs:element minOccurs="0" name="Sex" type="xs:string" />
+ <xs:element minOccurs="0" name="DateOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="PlaceOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="CountryOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="Nationality" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="IdentificationType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Value" type="xs:string" />
+ <xs:element minOccurs="0" name="Type" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PersonNameType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="PrefixedDegree" type="xs:string" />
+ <xs:element name="GivenName" type="xs:string" nillable="true" />
+ <xs:element name="FamilyName" type="xs:string" nillable="true" />
+ <xs:element minOccurs="0" name="SuffixedDegree" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AlternativeNameType">
+ <xs:sequence>
+ <xs:element name="FamilyName" type="xs:string" nillable="true" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PostalAddressType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="PostalCode" type="xs:string" />
+ <xs:element minOccurs="0" name="Municipality" type="xs:string" />
+ <xs:element minOccurs="0" name="Locality" type="xs:string" />
+ <xs:element minOccurs="0" name="StateCode3" type="xs:string" />
+ <xs:element minOccurs="0" name="DeliveryAddress" type="pd:DeliveryAddressType" />
+ <xs:element minOccurs="0" name="HistoricRecord" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DeliveryAddressType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="AddressLine" type="xs:string" />
+ <xs:element minOccurs="0" name="StreetName" type="xs:string" />
+ <xs:element minOccurs="0" name="BuildingNumber" type="xs:string" />
+ <xs:element minOccurs="0" name="Unit" type="xs:string" />
+ <xs:element minOccurs="0" name="DoorNumber" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://www.w3.org/2001/04/xmldsig-more#">
+ <xs:element name="ECDSAKeyValue" type="ecdsa:ECDSAKeyValueType" nillable="true" />
+ <xs:complexType name="ECDSAKeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DomainParameters" type="ecdsa:DomainParamsType" />
+ <xs:element name="PublicKey" type="ecdsa:ECPointType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DomainParamsType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="NamedCurve" type="ecdsa:NamedCurveType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="NamedCurveType">
+ <xs:attribute name="URN" type="xs:string" use="required" />
+ </xs:complexType>
+ <xs:complexType name="ECPointType">
+ <xs:sequence minOccurs="0">
+ <xs:element name="X" type="ecdsa:PrimeFieldElemType" />
+ <xs:element name="Y" type="ecdsa:PrimeFieldElemType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PrimeFieldElemType">
+ <xs:attribute name="Value" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://www.w3.org/2000/09/xmldsig#" xmlns="http://www.w3.org/2001/XMLSchema">
+ <xs:import namespace="http://www.w3.org/2001/04/xmldsig-more#" />
+ <xs:complexType name="KeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DSAKeyValue" type="dsig:DSAKeyValueType" />
+ <xs:element minOccurs="0" name="RSAKeyValue" type="dsig:RSAKeyValueType" />
+ <xs:element minOccurs="0" ref="ecdsa:ECDSAKeyValue" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DSAKeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="P" type="xs:string" />
+ <xs:element minOccurs="0" name="Q" type="xs:string" />
+ <xs:element minOccurs="0" name="J" type="xs:string" />
+ <xs:element minOccurs="0" name="G" type="xs:string" />
+ <xs:element minOccurs="0" name="Y" type="xs:string" />
+ <!-- https://www.w3.org/TR/xmldsig-core/ defines PgenCounter THEN Seed, SZR.wsdl used Seed BEFORE PgenCounter. To keep it backwards compatible but allow the usual order, both ways are allowed. -->
+ <xs:choice maxOccurs="unbounded">
+ <xs:element minOccurs="0" name="PgenCounter" type="xs:string" />
+ <xs:element minOccurs="0" name="Seed" type="xs:string" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RSAKeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Modulus" type="xs:string" />
+ <xs:element minOccurs="0" name="Exponent" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="urn:SZRServices">
+ <xs:import namespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" />
+ <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" />
+ <xs:element name="SZRException" type="szr:SZRException" />
+ <xs:complexType name="SZRException" />
+ <xs:complexType name="PersonInfoType">
+ <xs:sequence>
+ <xs:element name="Person" type="pd:PhysicalPersonType" />
+ <xs:element minOccurs="0" name="RegularDomicile" type="pd:PostalAddressType" />
+ <xs:element minOccurs="0" name="AddressCodes" type="szr:AddressCodesType" />
+ <xs:element minOccurs="0" name="TravelDocument" type="szr:TravelDocumentType" />
+ <xs:element minOccurs="0" name="DateOfBirthWildcard" type="xs:boolean" />
+ <xs:element minOccurs="0" name="AuskunftssperreGesetzt" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TravelDocumentType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DocumentNumber" type="xs:string" />
+ <xs:element minOccurs="0" name="DocumentType" type="xs:string" />
+ <xs:element minOccurs="0" name="IssueDate" type="xs:string" />
+ <xs:element minOccurs="0" name="IssuingAuthority" type="xs:string" />
+ <xs:element minOccurs="0" name="IssuingCountry" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AddressCodesType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="OKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="SKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="ADRCD" type="xs:string" />
+ <xs:element minOccurs="0" name="SUBCD" type="xs:string" />
+ <xs:element minOccurs="0" name="OBJNR" type="xs:string" />
+ <xs:element minOccurs="0" name="NTZLNR" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="TransformBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="InputBPK" type="xs:string" />
+ <xs:element name="InputBereichsKennung" type="xs:string" />
+ <xs:element name="Begruendung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TransformBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="TransformBPKReturn" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermission">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="VKZ" type="xs:string" />
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element minOccurs="0" name="ParticipantId" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermissionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetVKZPermissionReturn" type="szr:GetVKZPermissionResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="IdentityLinkType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="Assertion" type="xs:anyType" />
+ <xs:element minOccurs="0" name="AdditionalInfo" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ResultRecord">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="Register" type="xs:string" />
+ <xs:element name="bPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="NoInsert" />
+ <xs:enumeration value="InsertOnNoMatch" />
+ <xs:enumeration value="ForceInsert" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element minOccurs="0" name="Suchwizard" type="xs:boolean" />
+ <xs:element name="VKZ" type="xs:string" nillable="true" />
+ <xs:element minOccurs="0" name="BehoerdenKennzeichen" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ <xs:element minOccurs="0" name="Sessionid" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiResponseType">
+ <xs:complexContent>
+ <xs:extension base="szr:GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element name="FoundWithSuchwizard" type="xs:boolean" />
+ <xs:element name="Sessionid" type="xs:string" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" default="false" />
+ <xs:element minOccurs="1" name="VKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="BehoerdenKennzeichen" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ResultRecord" type="szr:ResultRecord" />
+ <xs:element name="InsertERnPResult" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedRequestType">
+ <xs:sequence>
+ <xs:element minOccurs="1" name="StammzahlEncrypted" type="xs:string" />
+ <xs:element minOccurs="0" name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="1" name="VKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedResponseType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="bPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" maxOccurs="unbounded" name="KeyValue" type="dsig:KeyValueType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkEidas">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkEidasResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element minOccurs="0" name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ <xs:element minOccurs="0" name="ListMultiplePersons" type="xs:boolean" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GetBPKReturn" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ <xs:element maxOccurs="5" minOccurs="0" name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKsResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ResultRecord" type="szr:GetBPKsResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="GetBPKsResponseType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ <xs:element minOccurs="0" name="Fault">
+ <xs:complexType>
+ <xs:attribute name="Code" type="xs:string" />
+ <xs:attribute name="String" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetBPKKombi">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiRequest" type="szr:GetBPKKombiRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKKombiResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiResponse" type="szr:GetBPKKombiResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPV">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVRequest" type="szr:GetBPKZPVRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPVResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVResponse" type="szr:GetBPKZPVResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKFromStammzahlEncryptedRequest" type="szr:GetBPKFromStammzahlEncryptedRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse" type="szr:GetBPKFromStammzahlEncryptedResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="IdentityLink" type="szr:IdentityLinkType" />
+ <xs:element name="BereichsKennung" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ValidateIdentityLinkReturn" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string" />
+ <xs:element name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="BasisZahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BPKzuBasiszahlReturn" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="FremdBPKRequestType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element name="VKZ" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="FremdBPKType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element name="FremdBPK" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetVKZPermissionResponseType">
+ <xs:sequence>
+ <xs:element name="isAllowed" type="xs:boolean" />
+ <xs:element minOccurs="0" name="behSchluessel" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="BasisZahl" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Bereich" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKTargets" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="BasiszahlZuBPKReturnType">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKs" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="BasiszahlZuBPKReturn" type="szr:BasiszahlZuBPKReturnType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ZMRAnwendungsIntegration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKTargets" type="szr:FremdBPKRequestType" />
+ <xs:element maxOccurs="unbounded" name="ZMRfremdbPK" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="ZMRAnwendungsIntegrationReturnType">
+ <xs:sequence>
+ <xs:element name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKs" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="ZMRAnwendungsIntegrationResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ZMRAnwendungsIntegrationReturn" type="szr:ZMRAnwendungsIntegrationReturnType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVersion" nillable="true" />
+ <xs:element name="GetVersionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Version" type="xs:string" />
+ <xs:element name="Revision" type="xs:string" />
+ <xs:element name="Time" type="xs:string" />
+ <xs:element name="IdentityLinkNotAfter" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:schema>
+ <xs:schema targetNamespace="http://egov.gv.at/pvp1.xsd">
+ <xs:include schemaLocation="pvp1.xsd" />
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.xmlsoap.org/ws/2002/04/secext">
+ <xs:element name="Security">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- add the pvpToken here. You can also uncomment the following line if you support XSD 1.1 -->
+ <!-- <xs:element ref="pvp:pvpToken" /> -->
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:anyAttribute processContents="lax" />
+ </xs:complexType>
+ </xs:element>
+ </xs:schema>
+ </types>
+ <message name="Header">
+ <part name="SecurityHeader" element="wsse:Security" />
+ </message>
+ <message name="GetIdentityLinkRequest">
+ <part element="szr:GetIdentityLink" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkResponse">
+ <part element="szr:GetIdentityLinkResponse" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkEidasRequest">
+ <part element="szr:GetIdentityLinkEidas" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkEidasResponse">
+ <part element="szr:GetIdentityLinkEidasResponse" name="parameters" />
+ </message>
+ <message name="GetBPKRequest">
+ <part element="szr:GetBPK" name="parameters" />
+ </message>
+ <message name="GetBPKResponse">
+ <part element="szr:GetBPKResponse" name="parameters" />
+ </message>
+ <message name="GetBPKsRequest">
+ <part element="szr:GetBPKs" name="parameters" />
+ </message>
+ <message name="GetBPKsResponse">
+ <part element="szr:GetBPKsResponse" name="parameters" />
+ </message>
+ <message name="GetBPKKombiRequest">
+ <part element="szr:GetBPKKombi" name="parameters" />
+ </message>
+ <message name="GetBPKKombiResponse">
+ <part element="szr:GetBPKKombiResponse" name="parameters" />
+ </message>
+ <message name="GetBPKZPVRequest">
+ <part element="szr:GetBPKZPV" name="parameters" />
+ </message>
+ <message name="GetBPKZPVResponse">
+ <part element="szr:GetBPKZPVResponse" name="parameters" />
+ </message>
+ <message name="GetBPKFromStammzahlEncryptedRequest">
+ <part element="szr:GetBPKFromStammzahlEncrypted" name="parameters" />
+ </message>
+ <message name="GetBPKFromStammzahlEncryptedResponse">
+ <part element="szr:GetBPKFromStammzahlEncryptedResponse" name="parameters" />
+ </message>
+ <message name="BPKzuBasiszahlRequest">
+ <part element="szr:BPKzuBasiszahl" name="parameters" />
+ </message>
+ <message name="BPKzuBasiszahlResponse">
+ <part element="szr:BPKzuBasiszahlResponse" name="parameters" />
+ </message>
+ <message name="BasiszahlZuBPKRequest">
+ <part element="szr:BasiszahlZuBPK" name="parameters" />
+ </message>
+ <message name="BasiszahlZuBPKResponse">
+ <part element="szr:BasiszahlZuBPKResponse" name="parameters" />
+ </message>
+ <message name="ValidateIdentityLinkRequest">
+ <part element="szr:ValidateIdentityLink" name="parameters" />
+ </message>
+ <message name="ValidateIdentityLinkResponse">
+ <part element="szr:ValidateIdentityLinkResponse" name="parameters" />
+ </message>
+ <message name="TransformBPKRequest">
+ <part element="szr:TransformBPK" name="parameters" />
+ </message>
+ <message name="TransformBPKResponse">
+ <part element="szr:TransformBPKResponse" name="parameters" />
+ </message>
+ <message name="GetVKZPermissionRequest">
+ <part element="szr:GetVKZPermission" name="parameters" />
+ </message>
+ <message name="GetVKZPermissionResponse">
+ <part element="szr:GetVKZPermissionResponse" name="parameters" />
+ </message>
+ <message name="ZMRAnwendungsIntegrationRequest">
+ <part element="szr:ZMRAnwendungsIntegration" name="parameters" />
+ </message>
+ <message name="ZMRAnwendungsIntegrationResponse">
+ <part element="szr:ZMRAnwendungsIntegrationResponse" name="parameters" />
+ </message>
+ <message name="GetStammzahlRequest">
+ <part element="szr:GetStammzahl" name="parameters" />
+ </message>
+ <message name="GetStammzahlResponse">
+ <part element="szr:GetStammzahlResponse" name="parameters" />
+ </message>
+ <message name="GetStammzahlEncryptedRequest">
+ <part element="szr:GetStammzahlEncrypted" name="parameters" />
+ </message>
+ <message name="GetStammzahlEncryptedResponse">
+ <part element="szr:GetStammzahlEncryptedResponse" name="parameters" />
+ </message>
+ <message name="GetVersionRequest">
+ <part element="szr:GetVersion" name="parameters" />
+ </message>
+ <message name="GetVersionResponse">
+ <part element="szr:GetVersionResponse" name="parameters" />
+ </message>
+ <message name="SZRException">
+ <part element="szr:SZRException" name="fault" />
+ </message>
+ <portType name="SZR">
+ <operation name="GetIdentityLink">
+ <input message="szr:GetIdentityLinkRequest" name="GetIdentityLinkRequest" />
+ <output message="szr:GetIdentityLinkResponse" name="GetIdentityLinkResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetIdentityLinkEidas">
+ <input message="szr:GetIdentityLinkEidasRequest" name="GetIdentityLinkEidasRequest" />
+ <output message="szr:GetIdentityLinkEidasResponse" name="GetIdentityLinkEidasResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPK">
+ <jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
+ <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
+ </jaxws:bindings>
+ <input message="szr:GetBPKRequest" name="GetBPKRequest" />
+ <output message="szr:GetBPKResponse" name="GetBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKs">
+ <input message="szr:GetBPKsRequest" name="GetBPKsRequest" />
+ <output message="szr:GetBPKsResponse" name="GetBPKsResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKKombi">
+ <input message="szr:GetBPKKombiRequest" name="GetBPKKombiRequest" />
+ <output message="szr:GetBPKKombiResponse" name="GetBPKKombiResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKZPV">
+ <input message="szr:GetBPKZPVRequest" name="GetBPKZPVRequest" />
+ <output message="szr:GetBPKZPVResponse" name="GetBPKZPVResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKFromStammzahlEncrypted">
+ <input message="szr:GetBPKFromStammzahlEncryptedRequest" name="GetBPKFromStammzahlEncryptedRequest" />
+ <output message="szr:GetBPKFromStammzahlEncryptedResponse" name="GetBPKFromStammzahlEncryptedResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="ValidateIdentityLink">
+ <input message="szr:ValidateIdentityLinkRequest" name="ValidateIdentityLinkRequest" />
+ <output message="szr:ValidateIdentityLinkResponse" name="ValidateIdentityLinkResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="TransformBPK">
+ <input message="szr:TransformBPKRequest" name="TransformBPKRequest" />
+ <output message="szr:TransformBPKResponse" name="TransformBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetVKZPermission">
+ <input message="szr:GetVKZPermissionRequest" name="GetVKZPermissionRequest" />
+ <output message="szr:GetVKZPermissionResponse" name="GetVKZPermissionResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="BPKzuBasiszahl">
+ <input message="szr:BPKzuBasiszahlRequest" name="BPKzuBasiszahlRequest" />
+ <output message="szr:BPKzuBasiszahlResponse" name="BPKzuBasiszahlResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="BasiszahlZuBPK">
+ <input message="szr:BasiszahlZuBPKRequest" name="BasiszahlZuBPKRequest" />
+ <output message="szr:BasiszahlZuBPKResponse" name="BasiszahlZuBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="ZMRAnwendungsIntegration">
+ <input message="szr:ZMRAnwendungsIntegrationRequest" name="ZMRAnwendungsIntegrationRequest" />
+ <output message="szr:ZMRAnwendungsIntegrationResponse" name="ZMRAnwendungsIntegrationResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetStammzahl">
+ <input message="szr:GetStammzahlRequest" name="GetStammzahlRequest" />
+ <output message="szr:GetStammzahlResponse" name="GetStammzahlResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetStammzahlEncrypted">
+ <input message="szr:GetStammzahlEncryptedRequest" name="GetStammzahlEncryptedRequest" />
+ <output message="szr:GetStammzahlEncryptedResponse" name="GetStammzahlEncryptedResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetVersion">
+ <input message="szr:GetVersionRequest" name="GetVersionRequest" />
+ <output message="szr:GetVersionResponse" name="GetVersionResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ </portType>
+ <binding name="SZRSoapBinding" type="szr:SZR">
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <operation name="GetIdentityLink">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetIdentityLinkRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetIdentityLinkResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetIdentityLinkEidas">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetIdentityLinkEidasRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetIdentityLinkEidasResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKs">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKsRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKsResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKKombi">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKKombiRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKKombiResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKZPV">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKZPVRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKZPVResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKFromStammzahlEncrypted">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKFromStammzahlEncryptedRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKFromStammzahlEncryptedResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetVKZPermission">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetVKZPermissionRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetVKZPermissionResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="ValidateIdentityLink">
+ <wsdlsoap:operation soapAction="" />
+ <input name="ValidateIdentityLinkRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="ValidateIdentityLinkResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="TransformBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="TransformBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="TransformBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="BPKzuBasiszahl">
+ <wsdlsoap:operation soapAction="" />
+ <input name="BPKzuBasiszahlRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="BPKzuBasiszahlResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="BasiszahlZuBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="BasiszahlZuBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="BasiszahlZuBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="ZMRAnwendungsIntegration">
+ <wsdlsoap:operation soapAction="" />
+ <input name="ZMRAnwendungsIntegrationRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="ZMRAnwendungsIntegrationResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetStammzahl">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetStammzahlRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetStammzahlResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetStammzahlEncrypted">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetStammzahlEncryptedRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetStammzahlEncryptedResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetVersion">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetVersionRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetVersionResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ </binding>
+ <service name="SZRService">
+ <port binding="szr:SZRSoapBinding" name="SZRBusinesspartnerTestumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/at.gv.bmi.szrsrv-b/services/SZR" />
+ </port>
+ <port binding="szr:SZRSoapBinding" name="SZRTestumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services-T/services/SZR" />
+ </port>
+ <port binding="szr:SZRSoapBinding" name="SZRProduktionsumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services/services/SZR" />
+ </port>
+ </service>
+</definitions> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.WSDL b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.WSDL
new file mode 100644
index 00000000..4ad2645a
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR-1.WSDL
@@ -0,0 +1,901 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions targetNamespace="urn:SZRServices" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:pvp="http://egov.gv.at/pvp1.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:szr="urn:SZRServices" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <types>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://reference.e-government.gv.at/namespace/persondata/20020228#">
+ <xs:complexType name="PhysicalPersonType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Identification" type="pd:IdentificationType" />
+ <xs:element minOccurs="1" name="Name" type="pd:PersonNameType" />
+ <xs:element minOccurs="0" name="AlternativeName" type="pd:AlternativeNameType" />
+ <xs:element minOccurs="0" name="Sex" type="xs:string" />
+ <xs:element minOccurs="0" name="DateOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="PlaceOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="CountryOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="Nationality" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="IdentificationType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Value" type="xs:string" />
+ <xs:element minOccurs="0" name="Type" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PersonNameType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="PrefixedDegree" type="xs:string" />
+ <xs:element name="GivenName" type="xs:string" nillable="true" />
+ <xs:element name="FamilyName" type="xs:string" nillable="true" />
+ <xs:element minOccurs="0" name="SuffixedDegree" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AlternativeNameType">
+ <xs:sequence>
+ <xs:element name="FamilyName" type="xs:string" nillable="true" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PostalAddressType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="PostalCode" type="xs:string" />
+ <xs:element minOccurs="0" name="Municipality" type="xs:string" />
+ <xs:element minOccurs="0" name="Locality" type="xs:string" />
+ <xs:element minOccurs="0" name="StateCode3" type="xs:string" />
+ <xs:element minOccurs="0" name="DeliveryAddress" type="pd:DeliveryAddressType" />
+ <xs:element minOccurs="0" name="HistoricRecord" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DeliveryAddressType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="AddressLine" type="xs:string" />
+ <xs:element minOccurs="0" name="StreetName" type="xs:string" />
+ <xs:element minOccurs="0" name="BuildingNumber" type="xs:string" />
+ <xs:element minOccurs="0" name="Unit" type="xs:string" />
+ <xs:element minOccurs="0" name="DoorNumber" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://www.w3.org/2001/04/xmldsig-more#">
+ <xs:element name="ECDSAKeyValue" type="ecdsa:ECDSAKeyValueType" nillable="true" />
+ <xs:complexType name="ECDSAKeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DomainParameters" type="ecdsa:DomainParamsType" />
+ <xs:element name="PublicKey" type="ecdsa:ECPointType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DomainParamsType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="NamedCurve" type="ecdsa:NamedCurveType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="NamedCurveType">
+ <xs:attribute name="URN" type="xs:string" use="required" />
+ </xs:complexType>
+ <xs:complexType name="ECPointType">
+ <xs:sequence minOccurs="0">
+ <xs:element name="X" type="ecdsa:PrimeFieldElemType" />
+ <xs:element name="Y" type="ecdsa:PrimeFieldElemType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PrimeFieldElemType">
+ <xs:attribute name="Value" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://www.w3.org/2000/09/xmldsig#" xmlns="http://www.w3.org/2001/XMLSchema">
+ <xs:import namespace="http://www.w3.org/2001/04/xmldsig-more#" />
+ <xs:complexType name="KeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DSAKeyValue" type="dsig:DSAKeyValueType" />
+ <xs:element minOccurs="0" name="RSAKeyValue" type="dsig:RSAKeyValueType" />
+ <xs:element minOccurs="0" ref="ecdsa:ECDSAKeyValue" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DSAKeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="P" type="xs:string" />
+ <xs:element minOccurs="0" name="Q" type="xs:string" />
+ <xs:element minOccurs="0" name="J" type="xs:string" />
+ <xs:element minOccurs="0" name="G" type="xs:string" />
+ <xs:element minOccurs="0" name="Y" type="xs:string" />
+ <!-- https://www.w3.org/TR/xmldsig-core/ defines PgenCounter THEN Seed, SZR.wsdl used Seed BEFORE PgenCounter. To keep it backwards compatible but allow the usual order, both ways are allowed. -->
+ <xs:choice maxOccurs="unbounded">
+ <xs:element minOccurs="0" name="PgenCounter" type="xs:string" />
+ <xs:element minOccurs="0" name="Seed" type="xs:string" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RSAKeyValueType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Modulus" type="xs:string" />
+ <xs:element minOccurs="0" name="Exponent" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="urn:SZRServices">
+ <xs:import namespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" />
+ <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" />
+ <xs:element name="SZRException" type="szr:SZRException" />
+ <xs:complexType name="SZRException" />
+ <xs:complexType name="PersonInfoType">
+ <xs:sequence>
+ <xs:element name="Person" type="pd:PhysicalPersonType" />
+ <xs:element minOccurs="0" name="RegularDomicile" type="pd:PostalAddressType" />
+ <xs:element minOccurs="0" name="AddressCodes" type="szr:AddressCodesType" />
+ <xs:element minOccurs="0" name="TravelDocument" type="szr:TravelDocumentType" />
+ <xs:element minOccurs="0" name="DateOfBirthWildcard" type="xs:boolean" />
+ <xs:element minOccurs="0" name="AuskunftssperreGesetzt" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TravelDocumentType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DocumentNumber" type="xs:string" />
+ <xs:element minOccurs="0" name="DocumentType" type="xs:string" />
+ <xs:element minOccurs="0" name="IssueDate" type="xs:string" />
+ <xs:element minOccurs="0" name="IssuingAuthority" type="xs:string" />
+ <xs:element minOccurs="0" name="IssuingCountry" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AddressCodesType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="OKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="SKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="ADRCD" type="xs:string" />
+ <xs:element minOccurs="0" name="SUBCD" type="xs:string" />
+ <xs:element minOccurs="0" name="OBJNR" type="xs:string" />
+ <xs:element minOccurs="0" name="NTZLNR" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="TransformBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="InputBPK" type="xs:string" />
+ <xs:element name="InputBereichsKennung" type="xs:string" />
+ <xs:element name="Begruendung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TransformBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="TransformBPKReturn" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermission">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="VKZ" type="xs:string" />
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element minOccurs="0" name="ParticipantId" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermissionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetVKZPermissionReturn" type="szr:GetVKZPermissionResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="IdentityLinkType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="Assertion" type="xs:anyType" />
+ <xs:element minOccurs="0" name="AdditionalInfo" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ResultRecord">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="Register" type="xs:string" />
+ <xs:element name="bPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="NoInsert" />
+ <xs:enumeration value="InsertOnNoMatch" />
+ <xs:enumeration value="ForceInsert" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element minOccurs="0" name="Suchwizard" type="xs:boolean" />
+ <xs:element name="VKZ" type="xs:string" nillable="true" />
+ <xs:element minOccurs="0" name="BehoerdenKennzeichen" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ <xs:element minOccurs="0" name="Sessionid" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiResponseType">
+ <xs:complexContent>
+ <xs:extension base="szr:GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element name="FoundWithSuchwizard" type="xs:boolean" />
+ <xs:element name="Sessionid" type="xs:string" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" default="false" />
+ <xs:element minOccurs="1" name="VKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="BehoerdenKennzeichen" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ResultRecord" type="szr:ResultRecord" />
+ <xs:element name="InsertERnPResult" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedRequestType">
+ <xs:sequence>
+ <xs:element minOccurs="1" name="StammzahlEncrypted" type="xs:string" />
+ <xs:element minOccurs="0" name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="1" name="VKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedResponseType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="bPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element maxOccurs="unbounded" name="KeyValue" type="dsig:KeyValueType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element minOccurs="0" name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ <xs:element minOccurs="0" name="ListMultiplePersons" type="xs:boolean" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GetBPKReturn" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ <xs:element maxOccurs="5" minOccurs="0" name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKsResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ResultRecord" type="szr:GetBPKsResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="GetBPKsResponseType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ <xs:element minOccurs="0" name="Fault">
+ <xs:complexType>
+ <xs:attribute name="Code" type="xs:string" />
+ <xs:attribute name="String" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetBPKKombi">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiRequest" type="szr:GetBPKKombiRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKKombiResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiResponse" type="szr:GetBPKKombiResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPV">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVRequest" type="szr:GetBPKZPVRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPVResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVResponse" type="szr:GetBPKZPVResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKFromStammzahlEncryptedRequest" type="szr:GetBPKFromStammzahlEncryptedRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse" type="szr:GetBPKFromStammzahlEncryptedResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="IdentityLink" type="szr:IdentityLinkType" />
+ <xs:element name="BereichsKennung" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ValidateIdentityLinkReturn" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string" />
+ <xs:element name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="BasisZahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BPKzuBasiszahlReturn" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="FremdBPKRequestType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element name="VKZ" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="FremdBPKType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element name="FremdBPK" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetVKZPermissionResponseType">
+ <xs:sequence>
+ <xs:element name="isAllowed" type="xs:boolean" />
+ <xs:element minOccurs="0" name="behSchluessel" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="BasisZahl" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Bereich" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKTargets" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="BasiszahlZuBPKReturnType">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKs" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="BasiszahlZuBPKReturn" type="szr:BasiszahlZuBPKReturnType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ZMRAnwendungsIntegration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKTargets" type="szr:FremdBPKRequestType" />
+ <xs:element maxOccurs="unbounded" name="ZMRfremdbPK" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="ZMRAnwendungsIntegrationReturnType">
+ <xs:sequence>
+ <xs:element name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKs" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="ZMRAnwendungsIntegrationResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ZMRAnwendungsIntegrationReturn" type="szr:ZMRAnwendungsIntegrationReturnType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVersion" />
+ <xs:element name="GetVersionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Version" type="xs:string" />
+ <xs:element name="Revision" type="xs:string" />
+ <xs:element name="Time" type="xs:string" />
+ <xs:element name="IdentityLinkNotAfter" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:schema>
+ <xs:schema targetNamespace="http://egov.gv.at/pvp1.xsd">
+ <xs:include schemaLocation="pvp1.xsd" />
+ </xs:schema>
+ <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.xmlsoap.org/ws/2002/04/secext">
+ <xs:element name="Security">
+ <xs:complexType>
+ <xs:sequence>
+ <!-- add the pvpToken here. You can also uncomment the following line if you support XSD 1.1 -->
+ <!-- <xs:element ref="pvp:pvpToken" /> -->
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:anyAttribute processContents="lax" />
+ </xs:complexType>
+ </xs:element>
+ </xs:schema>
+ </types>
+ <message name="Header">
+ <part name="SecurityHeader" element="wsse:Security" />
+ </message>
+ <message name="GetIdentityLinkRequest">
+ <part element="szr:GetIdentityLink" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkResponse">
+ <part element="szr:GetIdentityLinkResponse" name="parameters" />
+ </message>
+ <message name="GetBPKRequest">
+ <part element="szr:GetBPK" name="parameters" />
+ </message>
+ <message name="GetBPKResponse">
+ <part element="szr:GetBPKResponse" name="parameters" />
+ </message>
+ <message name="GetBPKsRequest">
+ <part element="szr:GetBPKs" name="parameters" />
+ </message>
+ <message name="GetBPKsResponse">
+ <part element="szr:GetBPKsResponse" name="parameters" />
+ </message>
+ <message name="GetBPKKombiRequest">
+ <part element="szr:GetBPKKombi" name="parameters" />
+ </message>
+ <message name="GetBPKKombiResponse">
+ <part element="szr:GetBPKKombiResponse" name="parameters" />
+ </message>
+ <message name="GetBPKZPVRequest">
+ <part element="szr:GetBPKZPV" name="parameters" />
+ </message>
+ <message name="GetBPKZPVResponse">
+ <part element="szr:GetBPKZPVResponse" name="parameters" />
+ </message>
+ <message name="GetBPKFromStammzahlEncryptedRequest">
+ <part element="szr:GetBPKFromStammzahlEncrypted" name="parameters" />
+ </message>
+ <message name="GetBPKFromStammzahlEncryptedResponse">
+ <part element="szr:GetBPKFromStammzahlEncryptedResponse" name="parameters" />
+ </message>
+ <message name="BPKzuBasiszahlRequest">
+ <part element="szr:BPKzuBasiszahl" name="parameters" />
+ </message>
+ <message name="BPKzuBasiszahlResponse">
+ <part element="szr:BPKzuBasiszahlResponse" name="parameters" />
+ </message>
+ <message name="BasiszahlZuBPKRequest">
+ <part element="szr:BasiszahlZuBPK" name="parameters" />
+ </message>
+ <message name="BasiszahlZuBPKResponse">
+ <part element="szr:BasiszahlZuBPKResponse" name="parameters" />
+ </message>
+ <message name="ValidateIdentityLinkRequest">
+ <part element="szr:ValidateIdentityLink" name="parameters" />
+ </message>
+ <message name="ValidateIdentityLinkResponse">
+ <part element="szr:ValidateIdentityLinkResponse" name="parameters" />
+ </message>
+ <message name="TransformBPKRequest">
+ <part element="szr:TransformBPK" name="parameters" />
+ </message>
+ <message name="TransformBPKResponse">
+ <part element="szr:TransformBPKResponse" name="parameters" />
+ </message>
+ <message name="GetVKZPermissionRequest">
+ <part element="szr:GetVKZPermission" name="parameters" />
+ </message>
+ <message name="GetVKZPermissionResponse">
+ <part element="szr:GetVKZPermissionResponse" name="parameters" />
+ </message>
+ <message name="ZMRAnwendungsIntegrationRequest">
+ <part element="szr:ZMRAnwendungsIntegration" name="parameters" />
+ </message>
+ <message name="ZMRAnwendungsIntegrationResponse">
+ <part element="szr:ZMRAnwendungsIntegrationResponse" name="parameters" />
+ </message>
+ <message name="GetStammzahlRequest">
+ <part element="szr:GetStammzahl" name="parameters" />
+ </message>
+ <message name="GetStammzahlResponse">
+ <part element="szr:GetStammzahlResponse" name="parameters" />
+ </message>
+ <message name="GetStammzahlEncryptedRequest">
+ <part element="szr:GetStammzahlEncrypted" name="parameters" />
+ </message>
+ <message name="GetStammzahlEncryptedResponse">
+ <part element="szr:GetStammzahlEncryptedResponse" name="parameters" />
+ </message>
+ <message name="GetVersionRequest">
+ <part element="szr:GetVersion" name="parameters" />
+ </message>
+ <message name="GetVersionResponse">
+ <part element="szr:GetVersionResponse" name="parameters" />
+ </message>
+ <message name="SZRException">
+ <part element="szr:SZRException" name="fault" />
+ </message>
+ <portType name="SZR">
+ <operation name="GetIdentityLink">
+ <input message="szr:GetIdentityLinkRequest" name="GetIdentityLinkRequest" />
+ <output message="szr:GetIdentityLinkResponse" name="GetIdentityLinkResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPK">
+ <jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
+ <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
+ </jaxws:bindings>
+ <input message="szr:GetBPKRequest" name="GetBPKRequest" />
+ <output message="szr:GetBPKResponse" name="GetBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKs">
+ <input message="szr:GetBPKsRequest" name="GetBPKsRequest" />
+ <output message="szr:GetBPKsResponse" name="GetBPKsResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKKombi">
+ <input message="szr:GetBPKKombiRequest" name="GetBPKKombiRequest" />
+ <output message="szr:GetBPKKombiResponse" name="GetBPKKombiResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKZPV">
+ <input message="szr:GetBPKZPVRequest" name="GetBPKZPVRequest" />
+ <output message="szr:GetBPKZPVResponse" name="GetBPKZPVResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKFromStammzahlEncrypted">
+ <input message="szr:GetBPKFromStammzahlEncryptedRequest" name="GetBPKFromStammzahlEncryptedRequest" />
+ <output message="szr:GetBPKFromStammzahlEncryptedResponse" name="GetBPKFromStammzahlEncryptedResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="ValidateIdentityLink">
+ <input message="szr:ValidateIdentityLinkRequest" name="ValidateIdentityLinkRequest" />
+ <output message="szr:ValidateIdentityLinkResponse" name="ValidateIdentityLinkResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="TransformBPK">
+ <input message="szr:TransformBPKRequest" name="TransformBPKRequest" />
+ <output message="szr:TransformBPKResponse" name="TransformBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetVKZPermission">
+ <input message="szr:GetVKZPermissionRequest" name="GetVKZPermissionRequest" />
+ <output message="szr:GetVKZPermissionResponse" name="GetVKZPermissionResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="BPKzuBasiszahl">
+ <input message="szr:BPKzuBasiszahlRequest" name="BPKzuBasiszahlRequest" />
+ <output message="szr:BPKzuBasiszahlResponse" name="BPKzuBasiszahlResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="BasiszahlZuBPK">
+ <input message="szr:BasiszahlZuBPKRequest" name="BasiszahlZuBPKRequest" />
+ <output message="szr:BasiszahlZuBPKResponse" name="BasiszahlZuBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="ZMRAnwendungsIntegration">
+ <input message="szr:ZMRAnwendungsIntegrationRequest" name="ZMRAnwendungsIntegrationRequest" />
+ <output message="szr:ZMRAnwendungsIntegrationResponse" name="ZMRAnwendungsIntegrationResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetStammzahl">
+ <input message="szr:GetStammzahlRequest" name="GetStammzahlRequest" />
+ <output message="szr:GetStammzahlResponse" name="GetStammzahlResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetStammzahlEncrypted">
+ <input message="szr:GetStammzahlEncryptedRequest" name="GetStammzahlEncryptedRequest" />
+ <output message="szr:GetStammzahlEncryptedResponse" name="GetStammzahlEncryptedResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetVersion">
+ <input message="szr:GetVersionRequest" name="GetVersionRequest" />
+ <output message="szr:GetVersionResponse" name="GetVersionResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ </portType>
+ <binding name="SZRSoapBinding" type="szr:SZR">
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <operation name="GetIdentityLink">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetIdentityLinkRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetIdentityLinkResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKs">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKsRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKsResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKKombi">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKKombiRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKKombiResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKZPV">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKZPVRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKZPVResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKFromStammzahlEncrypted">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKFromStammzahlEncryptedRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKFromStammzahlEncryptedResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetVKZPermission">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetVKZPermissionRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetVKZPermissionResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="ValidateIdentityLink">
+ <wsdlsoap:operation soapAction="" />
+ <input name="ValidateIdentityLinkRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="ValidateIdentityLinkResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="TransformBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="TransformBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="TransformBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="BPKzuBasiszahl">
+ <wsdlsoap:operation soapAction="" />
+ <input name="BPKzuBasiszahlRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="BPKzuBasiszahlResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="BasiszahlZuBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="BasiszahlZuBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="BasiszahlZuBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="ZMRAnwendungsIntegration">
+ <wsdlsoap:operation soapAction="" />
+ <input name="ZMRAnwendungsIntegrationRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="ZMRAnwendungsIntegrationResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetStammzahl">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetStammzahlRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetStammzahlResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetStammzahlEncrypted">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetStammzahlEncryptedRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetStammzahlEncryptedResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetVersion">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetVersionRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetVersionResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ </binding>
+ <service name="SZRService">
+ <port binding="szr:SZRSoapBinding" name="SZRBusinesspartnerTestumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/at.gv.bmi.szrsrv-b/services/SZR" />
+ </port>
+ <port binding="szr:SZRSoapBinding" name="SZRTestumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services-T/services/SZR" />
+ </port>
+ <port binding="szr:SZRSoapBinding" name="SZRProduktionsumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services/services/SZR" />
+ </port>
+ </service>
+</definitions> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl
new file mode 100644
index 00000000..e7f296bd
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions targetNamespace="urn:SZRServices" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:pvp="http://egov.gv.at/pvp1.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:szr="urn:SZRServices" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <types>
+ <xs:schema>
+ <xs:import namespace="urn:SZRServices" schemaLocation="szr_v4.0.xsd"/>
+ </xs:schema>
+ </types>
+ <message name="Header">
+ <part name="SecurityHeader" element="wsse:Security" />
+ </message>
+ <message name="GetIdentityLinkRequest">
+ <part element="szr:GetIdentityLink" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkResponse">
+ <part element="szr:GetIdentityLinkResponse" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkEidasRequest">
+ <part element="szr:GetIdentityLinkEidas" name="parameters" />
+ </message>
+ <message name="GetIdentityLinkEidasResponse">
+ <part element="szr:GetIdentityLinkEidasResponse" name="parameters" />
+ </message>
+ <message name="GetBPKRequest">
+ <part element="szr:GetBPK" name="parameters" />
+ </message>
+ <message name="GetBPKResponse">
+ <part element="szr:GetBPKResponse" name="parameters" />
+ </message>
+ <message name="GetBPKsRequest">
+ <part element="szr:GetBPKs" name="parameters" />
+ </message>
+ <message name="GetBPKsResponse">
+ <part element="szr:GetBPKsResponse" name="parameters" />
+ </message>
+ <message name="GetBPKKombiRequest">
+ <part element="szr:GetBPKKombi" name="parameters" />
+ </message>
+ <message name="GetBPKKombiResponse">
+ <part element="szr:GetBPKKombiResponse" name="parameters" />
+ </message>
+ <message name="GetBPKZPVRequest">
+ <part element="szr:GetBPKZPV" name="parameters" />
+ </message>
+ <message name="GetBPKZPVResponse">
+ <part element="szr:GetBPKZPVResponse" name="parameters" />
+ </message>
+ <message name="GetBPKFromStammzahlEncryptedRequest">
+ <part element="szr:GetBPKFromStammzahlEncrypted" name="parameters" />
+ </message>
+ <message name="GetBPKFromStammzahlEncryptedResponse">
+ <part element="szr:GetBPKFromStammzahlEncryptedResponse" name="parameters" />
+ </message>
+ <message name="SignContentRequest">
+ <part element="szr:SignContent" name="parameters" />
+ </message>
+ <message name="SignContentResponse">
+ <part element="szr:SignContentResponse" name="parameters" />
+ </message>
+ <message name="BPKzuBasiszahlRequest">
+ <part element="szr:BPKzuBasiszahl" name="parameters" />
+ </message>
+ <message name="BPKzuBasiszahlResponse">
+ <part element="szr:BPKzuBasiszahlResponse" name="parameters" />
+ </message>
+ <message name="BasiszahlZuBPKRequest">
+ <part element="szr:BasiszahlZuBPK" name="parameters" />
+ </message>
+ <message name="BasiszahlZuBPKResponse">
+ <part element="szr:BasiszahlZuBPKResponse" name="parameters" />
+ </message>
+ <message name="ValidateIdentityLinkRequest">
+ <part element="szr:ValidateIdentityLink" name="parameters" />
+ </message>
+ <message name="ValidateIdentityLinkResponse">
+ <part element="szr:ValidateIdentityLinkResponse" name="parameters" />
+ </message>
+ <message name="TransformBPKRequest">
+ <part element="szr:TransformBPK" name="parameters" />
+ </message>
+ <message name="TransformBPKResponse">
+ <part element="szr:TransformBPKResponse" name="parameters" />
+ </message>
+ <message name="GetVKZPermissionRequest">
+ <part element="szr:GetVKZPermission" name="parameters" />
+ </message>
+ <message name="GetVKZPermissionResponse">
+ <part element="szr:GetVKZPermissionResponse" name="parameters" />
+ </message>
+ <message name="ZMRAnwendungsIntegrationRequest">
+ <part element="szr:ZMRAnwendungsIntegration" name="parameters" />
+ </message>
+ <message name="ZMRAnwendungsIntegrationResponse">
+ <part element="szr:ZMRAnwendungsIntegrationResponse" name="parameters" />
+ </message>
+ <message name="GetStammzahlRequest">
+ <part element="szr:GetStammzahl" name="parameters" />
+ </message>
+ <message name="GetStammzahlResponse">
+ <part element="szr:GetStammzahlResponse" name="parameters" />
+ </message>
+ <message name="GetStammzahlEncryptedRequest">
+ <part element="szr:GetStammzahlEncrypted" name="parameters" />
+ </message>
+ <message name="GetStammzahlEncryptedResponse">
+ <part element="szr:GetStammzahlEncryptedResponse" name="parameters" />
+ </message>
+ <message name="GetVersionRequest">
+ <part element="szr:GetVersion" name="parameters" />
+ </message>
+ <message name="GetVersionResponse">
+ <part element="szr:GetVersionResponse" name="parameters" />
+ </message>
+ <message name="SZRException">
+ <part element="szr:SZRException" name="fault" />
+ </message>
+ <portType name="SZR">
+ <operation name="GetIdentityLink">
+ <input message="szr:GetIdentityLinkRequest" name="GetIdentityLinkRequest" />
+ <output message="szr:GetIdentityLinkResponse" name="GetIdentityLinkResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetIdentityLinkEidas">
+ <input message="szr:GetIdentityLinkEidasRequest" name="GetIdentityLinkEidasRequest" />
+ <output message="szr:GetIdentityLinkEidasResponse" name="GetIdentityLinkEidasResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPK">
+ <jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
+ <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
+ </jaxws:bindings>
+ <input message="szr:GetBPKRequest" name="GetBPKRequest" />
+ <output message="szr:GetBPKResponse" name="GetBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKs">
+ <input message="szr:GetBPKsRequest" name="GetBPKsRequest" />
+ <output message="szr:GetBPKsResponse" name="GetBPKsResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKKombi">
+ <input message="szr:GetBPKKombiRequest" name="GetBPKKombiRequest" />
+ <output message="szr:GetBPKKombiResponse" name="GetBPKKombiResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKZPV">
+ <input message="szr:GetBPKZPVRequest" name="GetBPKZPVRequest" />
+ <output message="szr:GetBPKZPVResponse" name="GetBPKZPVResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetBPKFromStammzahlEncrypted">
+ <input message="szr:GetBPKFromStammzahlEncryptedRequest" name="GetBPKFromStammzahlEncryptedRequest" />
+ <output message="szr:GetBPKFromStammzahlEncryptedResponse" name="GetBPKFromStammzahlEncryptedResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="SignContent">
+ <input message="szr:SignContentRequest" name="SignContentRequest" />
+ <output message="szr:SignContentResponse" name="SignContentResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="ValidateIdentityLink">
+ <input message="szr:ValidateIdentityLinkRequest" name="ValidateIdentityLinkRequest" />
+ <output message="szr:ValidateIdentityLinkResponse" name="ValidateIdentityLinkResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="TransformBPK">
+ <input message="szr:TransformBPKRequest" name="TransformBPKRequest" />
+ <output message="szr:TransformBPKResponse" name="TransformBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetVKZPermission">
+ <input message="szr:GetVKZPermissionRequest" name="GetVKZPermissionRequest" />
+ <output message="szr:GetVKZPermissionResponse" name="GetVKZPermissionResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="BPKzuBasiszahl">
+ <input message="szr:BPKzuBasiszahlRequest" name="BPKzuBasiszahlRequest" />
+ <output message="szr:BPKzuBasiszahlResponse" name="BPKzuBasiszahlResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="BasiszahlZuBPK">
+ <input message="szr:BasiszahlZuBPKRequest" name="BasiszahlZuBPKRequest" />
+ <output message="szr:BasiszahlZuBPKResponse" name="BasiszahlZuBPKResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="ZMRAnwendungsIntegration">
+ <input message="szr:ZMRAnwendungsIntegrationRequest" name="ZMRAnwendungsIntegrationRequest" />
+ <output message="szr:ZMRAnwendungsIntegrationResponse" name="ZMRAnwendungsIntegrationResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetStammzahl">
+ <input message="szr:GetStammzahlRequest" name="GetStammzahlRequest" />
+ <output message="szr:GetStammzahlResponse" name="GetStammzahlResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetStammzahlEncrypted">
+ <input message="szr:GetStammzahlEncryptedRequest" name="GetStammzahlEncryptedRequest" />
+ <output message="szr:GetStammzahlEncryptedResponse" name="GetStammzahlEncryptedResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ <operation name="GetVersion">
+ <input message="szr:GetVersionRequest" name="GetVersionRequest" />
+ <output message="szr:GetVersionResponse" name="GetVersionResponse" />
+ <fault message="szr:SZRException" name="SZRException" />
+ </operation>
+ </portType>
+ <binding name="SZRSoapBinding" type="szr:SZR">
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <operation name="GetIdentityLink">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetIdentityLinkRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetIdentityLinkResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetIdentityLinkEidas">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetIdentityLinkEidasRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetIdentityLinkEidasResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKs">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKsRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKsResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKKombi">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKKombiRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKKombiResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKZPV">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKZPVRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKZPVResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetBPKFromStammzahlEncrypted">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetBPKFromStammzahlEncryptedRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetBPKFromStammzahlEncryptedResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="SignContent">
+ <wsdlsoap:operation soapAction="" />
+ <input name="SignContentRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="SignContentResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetVKZPermission">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetVKZPermissionRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetVKZPermissionResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="ValidateIdentityLink">
+ <wsdlsoap:operation soapAction="" />
+ <input name="ValidateIdentityLinkRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="ValidateIdentityLinkResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="TransformBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="TransformBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="TransformBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="BPKzuBasiszahl">
+ <wsdlsoap:operation soapAction="" />
+ <input name="BPKzuBasiszahlRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="BPKzuBasiszahlResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="BasiszahlZuBPK">
+ <wsdlsoap:operation soapAction="" />
+ <input name="BasiszahlZuBPKRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="BasiszahlZuBPKResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="ZMRAnwendungsIntegration">
+ <wsdlsoap:operation soapAction="" />
+ <input name="ZMRAnwendungsIntegrationRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="ZMRAnwendungsIntegrationResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetStammzahl">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetStammzahlRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetStammzahlResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetStammzahlEncrypted">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetStammzahlEncryptedRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetStammzahlEncryptedResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ <operation name="GetVersion">
+ <wsdlsoap:operation soapAction="" />
+ <input name="GetVersionRequest">
+ <wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" />
+ <wsdlsoap:body use="literal" />
+ </input>
+ <output name="GetVersionResponse">
+ <wsdlsoap:body use="literal" />
+ </output>
+ <fault name="SZRException">
+ <wsdlsoap:fault name="SZRException" use="literal" />
+ </fault>
+ </operation>
+ </binding>
+ <service name="SZRService">
+ <port binding="szr:SZRSoapBinding" name="SZRBusinesspartnerTestumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/at.gv.bmi.szrsrv-b/services/SZR" />
+ </port>
+ <port binding="szr:SZRSoapBinding" name="SZRTestumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services-T/services/SZR" />
+ </port>
+ <port binding="szr:SZRSoapBinding" name="SZRProduktionsumgebung">
+ <wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services/services/SZR" />
+ </port>
+ </service>
+</definitions> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp1.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp1.xsd
new file mode 100644
index 00000000..09c0b1e3
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp1.xsd
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XMLSPY v2004 rel. 2 U (http://www.xmlspy.com) by BM (Bundeskanzleramt) -->
+<!-- PVP Schema 1.8.10 -->
+<!-- pvpToken wird über das Element <Security> aus der Spezifikation WS-Security in den SOAP-Header eingebunden -->
+<!--erstellt: rainer.hoerbe@bmi.gv.at 2004-04-30 -->
+<!--geändert: rainer.hoerbe@beko.at 2007-04-04: Extensions Points definiert -->
+<xs:schema targetNamespace="http://egov.gv.at/pvp1.xsd" xmlns="http://egov.gv.at/pvp1.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="pvpToken">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="pvpTokenType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="pvpTokenType">
+ <xs:sequence>
+ <xs:element name="authenticate">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="participantId" type="xs:string" />
+ <xs:element name="gvOuDomain" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:choice>
+ <xs:element name="userPrincipal">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="pvpPrincipalType">
+ <xs:sequence>
+ <xs:element name="gvGid" type="xs:string" />
+ <xs:element name="mail" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="tel" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="bpk" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="gvFunction" type="xs:string" minOccurs="0" maxOccurs="1" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="systemPrincipal" type="pvpPrincipalType" />
+ </xs:choice>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>additional authentication properties</xs:documentation>
+ </xs:annotation>
+ </xs:any>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="authorize" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:sequence minOccurs="0">
+ <xs:element name="gvOuId" type="xs:string" />
+ <xs:element name="ou" type="xs:string" />
+ </xs:sequence>
+ <xs:element name="role" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>additional authorization properties</xs:documentation>
+ </xs:annotation>
+ </xs:any>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="accounting" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pvpChainedToken" type="pvpTokenType" minOccurs="0" />
+ <xs:element name="pvpExtension" block="extension" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="version" type="gvVersionType" use="required" />
+ <xs:anyAttribute namespace="##any" processContents="lax" />
+ </xs:complexType>
+ <xs:complexType name="pvpPrincipalType">
+ <xs:sequence>
+ <xs:element name="userId" type="xs:string" />
+ <xs:element name="cn" type="xs:string" />
+ <xs:element name="gvOuId" type="xs:string" />
+ <xs:element name="ou" type="xs:string" />
+ <xs:element name="gvOuOKZ" type="xs:string" minOccurs="0" /> <!-- steht auch in der pvp doku, fehlt aber im normalen pvp1.xsd -->
+ <xs:element name="gvSecClass" type="gvSecClassType" minOccurs="0" />
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>additional principal attributes</xs:documentation>
+ </xs:annotation>
+ </xs:any>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##any" processContents="lax" />
+ </xs:complexType>
+ <xs:simpleType name="gvSecClassType">
+ <xs:restriction base="xs:integer">
+ <xs:enumeration value="0" />
+ <xs:enumeration value="1" />
+ <xs:enumeration value="2" />
+ <xs:enumeration value="3" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gvVersionType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="1.0" />
+ <xs:enumeration value="1.1" />
+ <xs:enumeration value="1.2" />
+ <xs:enumeration value="1.8" />
+ <xs:enumeration value="1.9" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="logLevelType">
+ <xs:restriction base="xs:integer">
+ <xs:enumeration value="0" />
+ <xs:enumeration value="1" />
+ <xs:enumeration value="2" />
+ <xs:enumeration value="3" />
+ <xs:enumeration value="4" />
+ <xs:enumeration value="5" />
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd
new file mode 100644
index 00000000..596a2b99
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XMLSPY v2004 rel. 2 U (http://www.xmlspy.com) by BM (Bundeskanzleramt) -->
+<!-- PVP Schema 1.8.10 -->
+<!-- pvpToken wird über das Element <Security> aus der Spezifikation WS-Security in den SOAP-Header eingebunden -->
+<!--erstellt: rainer.hoerbe@bmi.gv.at 2004-04-30 -->
+<!--geändert: rainer.hoerbe@beko.at 2007-04-04: Extensions Points definiert -->
+<xs:schema targetNamespace="http://egov.gv.at/pvp1.xsd" xmlns="http://egov.gv.at/pvp1.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="pvpToken">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="pvpTokenType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="pvpTokenType">
+ <xs:sequence>
+ <xs:element name="authenticate">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="participantId" type="xs:string" />
+ <xs:element name="gvOuDomain" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:choice>
+ <xs:element name="userPrincipal">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="pvpPrincipalType">
+ <xs:sequence>
+ <xs:element name="gvGid" type="xs:string" />
+ <xs:element name="mail" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="tel" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="bpk" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="gvFunction" type="xs:string" minOccurs="0" maxOccurs="1" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="systemPrincipal" type="pvpPrincipalType" />
+ </xs:choice>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>additional authentication properties</xs:documentation>
+ </xs:annotation>
+ </xs:any>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="authorize" minOccurs="0" maxOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:sequence minOccurs="0">
+ <xs:element name="gvOuId" type="xs:string" />
+ <xs:element name="ou" type="xs:string" />
+ </xs:sequence>
+ <xs:element name="role" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="value" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>additional authorization properties</xs:documentation>
+ </xs:annotation>
+ </xs:any>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="accounting" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pvpChainedToken" type="pvpTokenType" minOccurs="0" />
+ <xs:element name="pvpExtension" block="extension" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="version" type="gvVersionType" use="required" />
+ <xs:anyAttribute namespace="##any" processContents="lax" />
+ </xs:complexType>
+ <xs:complexType name="pvpPrincipalType">
+ <xs:sequence>
+ <xs:element name="userId" type="xs:string" />
+ <xs:element name="cn" type="xs:string" />
+ <xs:element name="gvOuId" type="xs:string" />
+ <xs:element name="ou" type="xs:string" />
+ <xs:element name="gvOuOKZ" type="xs:string" minOccurs="0" />
+ <xs:element name="gvSecClass" type="gvSecClassType" minOccurs="0" />
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>additional principal attributes</xs:documentation>
+ </xs:annotation>
+ </xs:any>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##any" processContents="lax" />
+ </xs:complexType>
+ <xs:simpleType name="gvSecClassType">
+ <xs:restriction base="xs:integer">
+ <xs:enumeration value="0" />
+ <xs:enumeration value="1" />
+ <xs:enumeration value="2" />
+ <xs:enumeration value="3" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="gvVersionType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="1.0" />
+ <xs:enumeration value="1.1" />
+ <xs:enumeration value="1.2" />
+ <xs:enumeration value="1.8" />
+ <xs:enumeration value="1.9" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="logLevelType">
+ <xs:restriction base="xs:integer">
+ <xs:enumeration value="0" />
+ <xs:enumeration value="1" />
+ <xs:enumeration value="2" />
+ <xs:enumeration value="3" />
+ <xs:enumeration value="4" />
+ <xs:enumeration value="5" />
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr.xsd
new file mode 100644
index 00000000..85acfb65
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr.xsd
@@ -0,0 +1,388 @@
+<xs:schema elementFormDefault="qualified" targetNamespace="urn:SZRServices" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:szr="urn:SZRServices" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import namespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" />
+ <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" />
+ <xs:element name="SZRException" type="szr:SZRException" />
+ <xs:complexType name="SZRException" />
+ <xs:complexType name="PersonInfoType">
+ <xs:sequence>
+ <xs:element name="Person" type="pd:PhysicalPersonType" />
+ <xs:element minOccurs="0" name="RegularDomicile" type="pd:PostalAddressType" />
+ <xs:element minOccurs="0" name="AddressCodes" type="szr:AddressCodesType" />
+ <xs:element minOccurs="0" name="TravelDocument" type="szr:TravelDocumentType" />
+ <xs:element minOccurs="0" name="DateOfBirthWildcard" type="xs:boolean" />
+ <xs:element minOccurs="0" name="AuskunftssperreGesetzt" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TravelDocumentType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="DocumentNumber" type="xs:string" />
+ <xs:element minOccurs="0" name="DocumentType" type="xs:string" />
+ <xs:element minOccurs="0" name="IssueDate" type="xs:string" />
+ <xs:element minOccurs="0" name="IssuingAuthority" type="xs:string" />
+ <xs:element minOccurs="0" name="IssuingCountry" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AddressCodesType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="OKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="SKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="ADRCD" type="xs:string" />
+ <xs:element minOccurs="0" name="SUBCD" type="xs:string" />
+ <xs:element minOccurs="0" name="OBJNR" type="xs:string" />
+ <xs:element minOccurs="0" name="NTZLNR" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="TransformBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="InputBPK" type="xs:string" />
+ <xs:element name="InputBereichsKennung" type="xs:string" />
+ <xs:element name="Begruendung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TransformBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="TransformBPKReturn" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermission">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="VKZ" type="xs:string" />
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element minOccurs="0" name="ParticipantId" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermissionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetVKZPermissionReturn" type="szr:GetVKZPermissionResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="IdentityLinkType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="Assertion" type="xs:anyType" />
+ <xs:element minOccurs="0" name="AdditionalInfo" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ResultRecord">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element name="Register" type="xs:string" />
+ <xs:element name="bPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="NoInsert" />
+ <xs:enumeration value="InsertOnNoMatch" />
+ <xs:enumeration value="ForceInsert" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element minOccurs="0" name="Suchwizard" type="xs:boolean" />
+ <xs:element name="VKZ" type="xs:string" nillable="true" />
+ <xs:element minOccurs="0" name="BehoerdenKennzeichen" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ <xs:element minOccurs="0" name="Sessionid" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiResponseType">
+ <xs:complexContent>
+ <xs:extension base="szr:GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element name="FoundWithSuchwizard" type="xs:boolean" />
+ <xs:element name="Sessionid" type="xs:string" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" default="false" />
+ <xs:element minOccurs="1" name="VKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="BehoerdenKennzeichen" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ResultRecord" type="szr:ResultRecord" />
+ <xs:element name="InsertERnPResult" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedRequestType">
+ <xs:sequence>
+ <xs:element minOccurs="1" name="StammzahlEncrypted" type="xs:string" />
+ <xs:element minOccurs="0" name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="1" name="VKZ" type="xs:string" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedResponseType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="bPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element maxOccurs="unbounded" name="KeyValue" type="dsig:KeyValueType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element minOccurs="0" name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ <xs:element minOccurs="0" name="ListMultiplePersons" type="xs:boolean" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GetBPKReturn" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ <xs:element maxOccurs="5" minOccurs="0" name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="BereichsKennung" type="xs:string" />
+ <xs:element name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Target" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKsResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ResultRecord" type="szr:GetBPKsResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="GetBPKsResponseType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPK" type="szr:FremdBPKType" />
+ <xs:element minOccurs="0" name="Fault">
+ <xs:complexType>
+ <xs:attribute name="Code" type="xs:string" />
+ <xs:attribute name="String" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetBPKKombi">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiRequest" type="szr:GetBPKKombiRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKKombiResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiResponse" type="szr:GetBPKKombiResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPV">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVRequest" type="szr:GetBPKZPVRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPVResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVResponse" type="szr:GetBPKZPVResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKFromStammzahlEncryptedRequest" type="szr:GetBPKFromStammzahlEncryptedRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse" type="szr:GetBPKFromStammzahlEncryptedResponseType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="IdentityLink" type="szr:IdentityLinkType" />
+ <xs:element name="BereichsKennung" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ValidateIdentityLinkReturn" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string" />
+ <xs:element name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="BasisZahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BPKzuBasiszahlReturn" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="FremdBPKRequestType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element name="VKZ" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="FremdBPKType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string" />
+ <xs:element name="FremdBPK" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetVKZPermissionResponseType">
+ <xs:sequence>
+ <xs:element name="isAllowed" type="xs:boolean" />
+ <xs:element minOccurs="0" name="behSchluessel" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="VKZ" type="xs:string" />
+ <xs:element maxOccurs="unbounded" name="BasisZahl" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Bereich" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKTargets" type="szr:FremdBPKRequestType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="BasiszahlZuBPKReturnType">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKs" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="BasiszahlZuBPKReturn" type="szr:BasiszahlZuBPKReturnType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ZMRAnwendungsIntegration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKTargets" type="szr:FremdBPKRequestType" />
+ <xs:element maxOccurs="unbounded" name="ZMRfremdbPK" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="ZMRAnwendungsIntegrationReturnType">
+ <xs:sequence>
+ <xs:element name="BPK" type="xs:string" />
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="FremdBPKs" type="szr:FremdBPKType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="ZMRAnwendungsIntegrationResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="ZMRAnwendungsIntegrationReturn" type="szr:ZMRAnwendungsIntegrationReturnType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" />
+ <xs:element minOccurs="0" name="InsertERnP" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVersion" />
+ <xs:element name="GetVersionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Version" type="xs:string" />
+ <xs:element name="Revision" type="xs:string" />
+ <xs:element name="Time" type="xs:string" />
+ <xs:element name="IdentityLinkNotAfter" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd
new file mode 100644
index 00000000..87ee80be
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.w3.org/2001/04/xmldsig-more#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#">
+ <xs:element name="ECDSAKeyValue" type="ecdsa:ECDSAKeyValueType" />
+ <xs:complexType name="ECDSAKeyValueType">
+ <xs:sequence>
+ <xs:element name="DomainParameters" type="ecdsa:DomainParamsType"
+ minOccurs="0" />
+ <xs:element name="PublicKey" type="ecdsa:ECPointType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DomainParamsType">
+ <xs:sequence>
+ <xs:element name="NamedCurve" minOccurs="0"
+ type="ecdsa:NamedCurveType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="NamedCurveType">
+ <xs:attribute name="URN" type="xs:string" use="required" />
+ </xs:complexType>
+ <xs:complexType name="ECPointType">
+ <xs:sequence minOccurs="0">
+ <xs:element name="X" type="ecdsa:PrimeFieldElemType" />
+ <xs:element name="Y" type="ecdsa:PrimeFieldElemType" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PrimeFieldElemType">
+ <xs:attribute name="Value" type="xs:string" use="required" />
+ </xs:complexType>
+</xs:schema> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd
new file mode 100644
index 00000000..3c9ac932
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema elementFormDefault="qualified" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#"
+ targetNamespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType name="PhysicalPersonType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Identification" type="pd:IdentificationType" />
+ <xs:element minOccurs="1" name="Name" type="pd:PersonNameType" />
+ <xs:element minOccurs="0" name="AlternativeName" type="pd:AlternativeNameType" />
+ <xs:element minOccurs="0" name="Sex" type="xs:string" />
+ <xs:element minOccurs="0" name="DateOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="PlaceOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="CountryOfBirth" type="xs:string" />
+ <xs:element minOccurs="0" name="Nationality" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="IdentificationType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="Value" type="xs:string" />
+ <xs:element minOccurs="0" name="Type" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PersonNameType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="PrefixedDegree" type="xs:string" />
+ <xs:element name="GivenName" type="xs:string" nillable="true" />
+ <xs:element name="FamilyName" type="xs:string" nillable="true" />
+ <xs:element minOccurs="0" name="SuffixedDegree" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AlternativeNameType">
+ <xs:sequence>
+ <xs:element name="FamilyName" type="xs:string" nillable="true" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PostalAddressType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="PostalCode" type="xs:string" />
+ <xs:element minOccurs="0" name="Municipality" type="xs:string" />
+ <xs:element minOccurs="0" name="Locality" type="xs:string" />
+ <xs:element minOccurs="0" name="StateCode3" type="xs:string" />
+ <xs:element minOccurs="0" name="DeliveryAddress" type="pd:DeliveryAddressType" />
+ <xs:element minOccurs="0" name="HistoricRecord" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DeliveryAddressType">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="AddressLine" type="xs:string" />
+ <xs:element minOccurs="0" name="StreetName" type="xs:string" />
+ <xs:element minOccurs="0" name="BuildingNumber" type="xs:string" />
+ <xs:element minOccurs="0" name="Unit" type="xs:string" />
+ <xs:element minOccurs="0" name="DoorNumber" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd
new file mode 100644
index 00000000..5001c1b8
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd
@@ -0,0 +1,10 @@
+<xs:schema xmlns:pvp="http://egov.gv.at/pvp1.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.xmlsoap.org/ws/2002/04/secext" elementFormDefault="qualified">
+ <xs:import namespace="http://egov.gv.at/pvp1.xsd" schemaLocation="pvp19.xsd"/>
+ <xs:element name="Security">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="pvp:pvpToken"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml
new file mode 100644
index 00000000..d40efa45
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
+
+ <bindings schemaLocation="../szr_v4/szr_v4.0.xsd">
+ <bindings node="/xsd:schema">
+ <schemaBindings>
+ <package name="at.gv.util.xsd.szr_v4" />
+ </schemaBindings>
+ </bindings>
+ </bindings>
+
+ <bindings schemaLocation="../szr/szr_ecdsa.xsd">
+ <bindings node="/xsd:schema">
+ <schemaBindings>
+ <package name="at.gv.util.xsd.szr.ecdsa" />
+ </schemaBindings>
+ </bindings>
+ </bindings>
+
+ <bindings schemaLocation="../szr_v4/szr_persondata.xsd">
+ <bindings node="/xsd:schema">
+ <schemaBindings>
+ <package name="at.gv.util.xsd.szr.persondata" />
+ </schemaBindings>
+ </bindings>
+ </bindings>
+
+ <bindings schemaLocation="../szr_v4/szr_pvp_sec.xsd">
+ <bindings node="/xsd:schema">
+ <schemaBindings>
+ <package name="at.gv.util.xsd.szr.pvp19.sec" />
+ </schemaBindings>
+ </bindings>
+ </bindings>
+
+ <bindings schemaLocation="../szr_v4/pvp19.xsd">
+ <bindings node="/xsd:schema">
+ <schemaBindings>
+ <package name="at.gv.util.xsd.szr.pvp19" />
+ </schemaBindings>
+ </bindings>
+ </bindings>
+
+ <bindings schemaLocation="../szr/szr_xmldsig.xsd">
+ <bindings node="/xsd:schema">
+ <schemaBindings>
+ <package name="at.gv.util.xsd.szr.xmldsig" />
+ </schemaBindings>
+ </bindings>
+ </bindings>
+
+</bindings> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml
new file mode 100644
index 00000000..f95c35f0
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bindings xmlns="http://java.sun.com/xml/ns/jaxws"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+
+ <enableWrapperStyle>false</enableWrapperStyle>
+ <package name="at.gv.util.wsdl.szr_v4"/>
+
+</bindings> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd
new file mode 100644
index 00000000..2d25f2dc
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd
@@ -0,0 +1,443 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:szr="urn:SZRServices" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" targetNamespace="urn:SZRServices" elementFormDefault="qualified">
+ <xs:import namespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" schemaLocation="szr_persondata.xsd"/>
+ <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="szr_xmldsig.xsd"/>
+ <xs:element name="SZRException" type="szr:SZRException"/>
+ <xs:complexType name="SZRException"/>
+ <xs:complexType name="PersonInfoType">
+ <xs:sequence>
+ <xs:element name="Person" type="pd:PhysicalPersonType"/>
+ <xs:element name="RegularDomicile" type="pd:PostalAddressType" minOccurs="0"/>
+ <xs:element name="AddressCodes" type="szr:AddressCodesType" minOccurs="0"/>
+ <xs:element name="TravelDocument" type="szr:TravelDocumentType" minOccurs="0"/>
+ <xs:element name="DateOfBirthWildcard" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="AuskunftssperreGesetzt" type="xs:boolean" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TravelDocumentType">
+ <xs:sequence>
+ <xs:element name="DocumentNumber" type="xs:string" minOccurs="0"/>
+ <xs:element name="DocumentType" type="xs:string" minOccurs="0"/>
+ <xs:element name="IssueDate" type="xs:string" minOccurs="0"/>
+ <xs:element name="IssuingAuthority" type="xs:string" minOccurs="0"/>
+ <xs:element name="IssuingCountry" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AddressCodesType">
+ <xs:sequence>
+ <xs:element name="GKZ" type="xs:string" minOccurs="0"/>
+ <xs:element name="OKZ" type="xs:string" minOccurs="0"/>
+ <xs:element name="SKZ" type="xs:string" minOccurs="0"/>
+ <xs:element name="ADRCD" type="xs:string" minOccurs="0"/>
+ <xs:element name="SUBCD" type="xs:string" minOccurs="0"/>
+ <xs:element name="OBJNR" type="xs:string" minOccurs="0"/>
+ <xs:element name="NTZLNR" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="TransformBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="InputBPK" type="xs:string"/>
+ <xs:element name="InputBereichsKennung" type="xs:string"/>
+ <xs:element name="Begruendung" type="xs:string"/>
+ <xs:element name="Target" type="szr:FremdBPKRequestType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TransformBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="TransformBPKReturn" type="szr:FremdBPKType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermission">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="VKZ" type="xs:string"/>
+ <xs:element name="BereichsKennung" type="xs:string"/>
+ <xs:element name="ParticipantId" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVKZPermissionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetVKZPermissionReturn" type="szr:GetVKZPermissionResponseType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="IdentityLinkType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="Assertion" type="xs:anyType"/>
+ <xs:element name="AdditionalInfo" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ResultRecord">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="Register" type="xs:string"/>
+ <xs:element name="bPK" type="xs:string"/>
+ <xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="InsertERnP" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="NoInsert"/>
+ <xs:enumeration value="InsertOnNoMatch"/>
+ <xs:enumeration value="ForceInsert"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="Suchwizard" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="VKZ" type="xs:string" nillable="true"/>
+ <xs:element name="BehoerdenKennzeichen" type="xs:string" minOccurs="0"/>
+ <xs:element name="BereichsKennung" type="xs:string" minOccurs="0"/>
+ <xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Sessionid" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKKombiResponseType">
+ <xs:complexContent>
+ <xs:extension base="szr:GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element name="FoundWithSuchwizard" type="xs:boolean"/>
+ <xs:element name="Sessionid" type="xs:string"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVRequestType">
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="InsertERnP" type="xs:boolean" default="false" minOccurs="0"/>
+ <xs:element name="VKZ" type="xs:string" minOccurs="1"/>
+ <xs:element name="BehoerdenKennzeichen" type="xs:string" minOccurs="0"/>
+ <xs:element name="BereichsKennung" type="xs:string" minOccurs="0"/>
+ <xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKZPVResponseType">
+ <xs:sequence>
+ <xs:element name="ResultRecord" type="szr:ResultRecord" maxOccurs="unbounded"/>
+ <xs:element name="InsertERnPResult" type="xs:boolean"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedRequestType">
+ <xs:sequence>
+ <xs:element name="StammzahlEncrypted" type="xs:string" minOccurs="1"/>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" minOccurs="0"/>
+ <xs:element name="VKZ" type="xs:string" minOccurs="1"/>
+ <xs:element name="BereichsKennung" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="key"/>
+ </xs:complexType>
+ <xs:complexType name="GetBPKFromStammzahlEncryptedResponseType">
+ <xs:sequence>
+ <xs:element name="bPK" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Fault" type="szr:Fault" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="key"/>
+ </xs:complexType>
+ <xs:complexType name="Fault">
+ <xs:attribute name="Code" type="xs:string"/>
+ <xs:attribute name="String" type="xs:string"/>
+ </xs:complexType>
+ <xs:complexType name="SignContentResponseType">
+ <xs:sequence>
+ <xs:element name="JwsAlg" type="xs:string" minOccurs="0"/>
+ <xs:element name="Out" type="szr:SignContentEntry" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="SignContentEntry">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="key"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:element name="GetIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="KeyValue" type="dsig:KeyValueType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="InsertERnP" type="xs:boolean" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkEidas">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetIdentityLinkEidasResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="BereichsKennung" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="VKZ" type="xs:string" minOccurs="0"/>
+ <xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ListMultiplePersons" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="InsertERnP" type="xs:boolean" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKReturn" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" minOccurs="0" maxOccurs="5"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType" maxOccurs="unbounded"/>
+ <xs:element name="BereichsKennung" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="VKZ" type="xs:string"/>
+ <xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKsResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ResultRecord" type="szr:GetBPKsResponseType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="GetBPKsResponseType">
+ <xs:sequence>
+ <xs:element name="BPK" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Fault" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="Code" type="xs:string"/>
+ <xs:attribute name="String" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="GetBPKKombi">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiRequest" type="szr:GetBPKKombiRequestType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKKombiResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKKombiResponse" type="szr:GetBPKKombiResponseType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPV">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVRequest" type="szr:GetBPKZPVRequestType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKZPVResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GetBPKZPVResponse" type="szr:GetBPKZPVResponseType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="In" type="szr:GetBPKFromStammzahlEncryptedRequestType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetBPKFromStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Out" type="szr:GetBPKFromStammzahlEncryptedResponseType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="SignContent">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="AppendCert" type="xs:boolean" default="false" minOccurs="0"/>
+ <xs:element name="JWSHeaderParam" type="szr:JwsHeaderParam" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="In" type="szr:SignContentEntry" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="JwsHeaderParam">
+ <xs:attribute name="key" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:element name="SignContentResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="SignContentResponse" type="szr:SignContentResponseType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLink">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="IdentityLink" type="szr:IdentityLinkType"/>
+ <xs:element name="BereichsKennung" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidateIdentityLinkResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ValidateIdentityLinkReturn" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string"/>
+ <xs:element name="BPK" type="xs:string"/>
+ <xs:element name="BasisZahl" type="xs:string" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="BPKzuBasiszahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BPKzuBasiszahlReturn" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="FremdBPKRequestType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string"/>
+ <xs:element name="VKZ" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="FremdBPKType">
+ <xs:sequence>
+ <xs:element name="BereichsKennung" type="xs:string"/>
+ <xs:element name="FremdBPK" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GetVKZPermissionResponseType">
+ <xs:sequence>
+ <xs:element name="isAllowed" type="xs:boolean"/>
+ <xs:element name="behSchluessel" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPK">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="VKZ" type="xs:string" minOccurs="0"/>
+ <xs:element name="BasisZahl" type="xs:string" maxOccurs="unbounded"/>
+ <xs:element name="Bereich" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="FremdBPKTargets" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="BasiszahlZuBPKReturnType">
+ <xs:sequence>
+ <xs:element name="BPK" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="FremdBPKs" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="BasiszahlZuBPKResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="BasiszahlZuBPKReturn" type="szr:BasiszahlZuBPKReturnType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ZMRAnwendungsIntegration">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Bereich" type="xs:string"/>
+ <xs:element name="FremdBPKTargets" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="ZMRfremdbPK" type="xs:string" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="ZMRAnwendungsIntegrationReturnType">
+ <xs:sequence>
+ <xs:element name="BPK" type="xs:string"/>
+ <xs:element name="FremdBPKs" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="ZMRAnwendungsIntegrationResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ZMRAnwendungsIntegrationReturn" type="szr:ZMRAnwendungsIntegrationReturnType" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahl">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncrypted">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PersonInfo" type="szr:PersonInfoType"/>
+ <xs:element name="InsertERnP" type="xs:boolean" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetStammzahlEncryptedResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Stammzahl" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetVersion" nillable="true"/>
+ <xs:element name="GetVersionResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Version" type="xs:string"/>
+ <xs:element name="Revision" type="xs:string"/>
+ <xs:element name="Time" type="xs:string"/>
+ <xs:element name="IdentityLinkNotAfter" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd
new file mode 100644
index 00000000..96b50b40
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#"
+ targetNamespace="http://www.w3.org/2000/09/xmldsig#" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+ <xs:import namespace="http://www.w3.org/2001/04/xmldsig-more#" schemaLocation="szr_ecdsa.xsd"/>
+ <xs:complexType name="KeyValueType">
+ <xs:sequence>
+ <xs:element name="DSAKeyValue" minOccurs="0"
+ type="dsig:DSAKeyValueType" />
+ <xs:element name="RSAKeyValue" minOccurs="0"
+ type="dsig:RSAKeyValueType" />
+ <xs:element ref="ecdsa:ECDSAKeyValue" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DSAKeyValueType">
+ <xs:sequence>
+ <xs:element name="P" minOccurs="0" type="xs:string" />
+ <xs:element name="Q" minOccurs="0" type="xs:string" />
+ <xs:element name="J" minOccurs="0" type="xs:string" />
+ <xs:element name="G" minOccurs="0" type="xs:string" />
+ <xs:element name="Y" minOccurs="0" type="xs:string" />
+ <xs:element name="PgenCounter" minOccurs="0" type="xs:string" />
+ <xs:element name="Seed" minOccurs="0" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RSAKeyValueType">
+ <xs:sequence>
+ <xs:element name="Modulus" minOccurs="0" type="xs:string" />
+ <xs:element name="Exponent" minOccurs="0" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/templates/eidas_node_forward.html b/modules/authmodule-eIDAS-v2/src/main/resources/templates/eidas_node_forward.html
new file mode 100644
index 00000000..186937d7
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/resources/templates/eidas_node_forward.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="fragments/base"
+ th:with="lang=${#locale.language}" th:lang="${lang}">
+<head>
+ <script src="$contextPath/autocommit.js"
+ th:attr="src=@{/autocommit.js}"></script>
+</head>
+<body>
+ <noscript>
+ <p>
+ <strong>Note:</strong> Since your browser does not support
+ JavaScript, you must press the Continue button once to proceed.
+ </p>
+ </noscript>
+
+ <div id="alert">Your login is being processed. Thank you for
+ waiting.</div>
+
+ <form action="${endPoint}" method="post" target="_parent"
+ th:attr="action=@{${endPoint}}">
+ <div>
+ <input type="hidden" name="${tokenName}" value="${tokenValue}"
+ th:attr="value=${tokenValue},name=${tokenName}" />
+ </div>
+ <noscript>
+ <div>
+ <p>Your browser does not support JavaScript. Click the button to continuing the process .</p>
+ <input type="submit" value="Continue" />
+ </div>
+ </noscript>
+ </form>
+
+</body>
+</html> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthSpringResourceProviderTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthSpringResourceProviderTest.java
new file mode 100644
index 00000000..aef290f5
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthSpringResourceProviderTest.java
@@ -0,0 +1,56 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.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.asitplus.eidas.specific.modules.auth.eidas.v2.EidasAuthenticationSpringResourceProvider;
+import at.gv.egiz.eaaf.core.test.TestConstants;
+
+
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class EidasAuthSpringResourceProviderTest {
+
+ @Test
+ public void testSpringConfig() {
+ final EidasAuthenticationSpringResourceProvider test =
+ new EidasAuthenticationSpringResourceProvider();
+ 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",
+ EidasAuthenticationSpringResourceProvider.class.getName(), spiFile);
+
+
+ } catch (final IOException e) {
+ Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found");
+
+ }
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthenticationModulImplTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthenticationModulImplTest.java
new file mode 100644
index 00000000..86af87ad
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasAuthenticationModulImplTest.java
@@ -0,0 +1,121 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasAuthenticationModulImpl;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.ModuleRegistration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
+public class EidasAuthenticationModulImplTest {
+
+ @Autowired ModuleRegistration moduleReg;
+ @Autowired ResourceLoader loader;
+
+ private final ExecutionContext executionContext = new ExecutionContextImpl();
+ private DummySpConfiguration oaParam;
+ private TestRequestImpl pendingReq;
+ private EidasAuthenticationModulImpl authProcess = new EidasAuthenticationModulImpl();
+
+ /**
+ * jUnit class initializer.
+ *
+ */
+ @BeforeClass
+ public static void classInitializer() throws IOException {
+ final String current = new java.io.File(".").toURI().toString();
+ System.setProperty("eidas.ms.configuration", current + "../../basicConfig/default_config.properties");
+
+ }
+
+ /**
+ * jUnit test set-up.
+ *
+ */
+ @Before
+ public void initialize() {
+ Map<String, String> configMap = new HashMap<String, String>();
+ configMap.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "http://test.com/test");
+ IConfiguration basicConfig = new DummyConfiguration();
+ oaParam = new DummySpConfiguration(configMap, basicConfig);
+ pendingReq = new TestRequestImpl();
+ pendingReq.setSpConfig(oaParam);
+ }
+
+ @Test
+ public void checkProcessDefinition() {
+ Assert.assertNotNull("AuthModule is null", authProcess);
+ Assert.assertNotNull("AuthModule process is null", authProcess.getProcessDefinitions());
+
+ for (String el : authProcess.getProcessDefinitions()) {
+ Resource res = loader.getResource(el);
+ Assert.assertTrue("AuthProcess description not extist", res.exists());
+
+ }
+ }
+
+ @Test
+ public void countrySelected() throws Exception {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, RandomStringUtils.randomAlphanumeric(2));
+ final String result =
+ moduleReg.selectProcess(executionContext, pendingReq);
+ Assert.assertNotNull("Process is null", result);
+ Assert.assertEquals("Process Id not match", "eIDASAuthentication_v2", result);
+
+ }
+
+ @Test
+ public void noCountryValid() throws Exception {
+ final String result =
+ moduleReg.selectProcess(executionContext, pendingReq);
+
+ Assert.assertNull("Select wrong process", result);
+
+ }
+
+ @Test
+ public void selectCountryWrongType() throws Exception {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, 1);
+ final String result =
+ moduleReg.selectProcess(executionContext, pendingReq);
+ Assert.assertNull("Select wrong process", result);
+
+ }
+
+ @Test
+ public void selectCountryEmpty() throws Exception {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "");
+ final String result =
+ moduleReg.selectProcess(executionContext, pendingReq);
+ Assert.assertNull("Select wrong process", result);
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasDataStoreTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasDataStoreTest.java
new file mode 100644
index 00000000..1051bd9f
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasDataStoreTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.test;
+
+//import java.security.MessageDigest;
+//
+//import org.apache.commons.lang3.StringUtils;
+//import org.junit.Test;
+//import org.junit.runner.RunWith;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.test.context.ContextConfiguration;
+//import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+//import org.springframework.util.Base64Utils;
+//
+//import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SQLiteServiceException;
+//import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.eIDASAuthenticationException;
+//import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.eIDASResponseUtils;
+//import at.gv.egiz.eaaf.core.impl.data.Trible;
+//
+//@RunWith(SpringJUnit4ClassRunner.class)
+//@ContextConfiguration("/SpringTest-context_basic_test.xml")
+//public class EidasDataStoreTest {
+//
+// @Autowired
+// private EidasDataStore dataStore;
+//
+// private static final String P1_TRANSID = "123456789";
+// private static final String P1_eIDASID =
+// "DE/AT/121asdf1as5f1as6f1asd2f1asdf1asdf1asd23f1asdf1asdf4sd7fsdf1asdf1asd2f1asd56f7asdf4asdfasdf1";
+//
+// private static final String P2_TRANSID = "987654321";
+// private static final String P2_eIDASID =
+// "EE/AT/asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd";
+//
+// @Test
+// public void dummyTest() {
+//
+// }
+//
+// @Test
+// public void insertTestOne() throws SQLiteServiceException, eIDASAuthenticationException {
+// Trible<String, String, String> eidasId = eIDASResponseUtils.parseEidasPersonalIdentifier(P1_eIDASID);
+// String ernbId = createHashFromUniqueId(eidasId.getThird());
+// dataStore.storeNationalId(
+// P1_TRANSID,
+// eidasId,
+// ernbId);
+//
+// if (StringUtils.isEmpty(dataStore.getEidasRawNationalId(ernbId)) {
+// && dataStore.getEidasRawNationalId(ernbId).equals(eidasId.getThird()))
+// throw new SQLiteServiceException("No eIDAS RAW Id in SQLite DB", null);
+//
+// }
+//
+// if (StringUtils.isEmpty(dataStore.getErnbNationalId(eidasId)) {
+// && dataStore.getErnbNationalId(eidasId).equals(ernbId))
+// throw new SQLiteServiceException("No ERnB Id in SQLite DB", null);
+// }
+//
+// }
+//
+// @Test
+// public void insertTestTwo() throws SQLiteServiceException, eIDASAuthenticationException {
+// Trible<String, String, String> eidasId = eIDASResponseUtils.parseEidasPersonalIdentifier(P2_eIDASID);
+// String ernbId = createHashFromUniqueId(eidasId.getThird());
+// dataStore.storeNationalId(
+// P2_TRANSID,
+// eidasId,
+// ernbId);
+//
+// if (StringUtils.isEmpty(dataStore.getEidasRawNationalId(ernbId)) {
+// && dataStore.getEidasRawNationalId(ernbId).equals(eidasId.getThird()))
+// throw new SQLiteServiceException("No eIDAS RAW Id in SQLite DB", null);
+//
+// }
+//
+// if (StringUtils.isEmpty(dataStore.getErnbNationalId(eidasId)) {
+// && dataStore.getErnbNationalId(eidasId).equals(ernbId))
+// throw new SQLiteServiceException("No ERnB Id in SQLite DB", null);
+//
+// }
+//
+// }
+//
+// private String createHashFromUniqueId(String uniqueId) throws eIDASAuthenticationException {
+// try {
+// MessageDigest md = MessageDigest.getInstance("SHA-256");
+// byte[] hash = md.digest(uniqueId.getBytes("UTF-8"));
+// String hashBase64 = new String(Base64Utils.encode(hash), "UTF-8").replaceAll("\r\n", "");
+// return hashBase64;
+//
+// } catch (Exception ex) {
+// throw new eIDASAuthenticationException("internal.03", new Object[] {}, ex);
+//
+// }
+// }
+//}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasSignalServletTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasSignalServletTest.java
new file mode 100644
index 00000000..0d9d4fb8
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasSignalServletTest.java
@@ -0,0 +1,244 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummySpConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyProtocolAuthService;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse.Builder;
+import eu.eidas.auth.commons.tx.BinaryLightToken;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+@EnableWebMvc
+public class EidasSignalServletTest {
+
+ @Autowired private MsConnectorDummyConfigMap basicConfig;
+ @Autowired private EidasSignalServlet controller;
+ @Autowired private IRequestStorage storage;
+ @Autowired private ITransactionStorage transStore;
+ @Autowired private DummyProtocolAuthService protAuthService;
+ @Autowired private DummySpecificCommunicationService connector;
+
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+ private MsConnectorDummySpConfiguration oaParam;
+
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new MsConnectorDummySpConfiguration(spConfig, basicConfig);
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+ pendingReq = new TestRequestImpl();
+
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+ pendingReq.setTransactionId("avaasbav");
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+
+ connector.setiLightResponse(null);
+
+
+ }
+
+ @Test
+ public void noResponsToken() throws IOException, EaafException {
+ //set-up
+
+ //execute test
+ controller.restoreEidasAuthProcess(httpReq, httpResp);
+
+ //validate state
+ Assert.assertNull("eIDAS response", httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertNotNull("missing error", protAuthService.getException());
+ Assert.assertEquals("Wrong errorId", "auth.26",
+ ((EaafException) protAuthService.getException()).getErrorId());
+
+ }
+
+ @Test
+ public void unknownResponseToken() throws IOException, EaafException {
+ //set-up
+ httpReq.setParameter(EidasParameterKeys.TOKEN.toString(),
+ RandomStringUtils.randomAlphanumeric(10));
+
+ //execute test
+ controller.restoreEidasAuthProcess(httpReq, httpResp);
+
+ //validate state
+ Assert.assertNull("eIDAS response", httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertNotNull("missing error", protAuthService.getException());
+ Assert.assertEquals("Wrong errorId", "auth.26",
+ ((EaafException) protAuthService.getException()).getErrorId());
+
+ }
+
+ @Test
+ public void withRelayState() throws IOException, EaafException, SpecificCommunicationException {
+ //set-up
+ String relayState = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setPendingReqId(relayState);
+ storage.storePendingRequest(pendingReq);
+
+ Builder iLightResponse = new AuthenticationResponse.Builder();
+ iLightResponse.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(Constants.SUCCESS_URI)
+ .inResponseTo("_".concat(Random.nextHexRandom16()))
+ .subjectNameIdFormat("afaf")
+ .relayState(relayState);
+
+ AuthenticationResponse eidasResp = iLightResponse.build();
+ BinaryLightToken token = connector.putResponse(eidasResp);
+ httpReq.setParameter(EidasParameterKeys.TOKEN.toString(),
+ Base64.getEncoder().encodeToString(token.getTokenBytes()));
+
+
+ //execute test
+ controller.restoreEidasAuthProcess(httpReq, httpResp);
+
+
+ //validate state
+ Assert.assertNotNull("eIDAS response", httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertEquals("wrong eIDAS response", eidasResp,
+ httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+
+ Assert.assertNotNull("missing error", protAuthService.getException());
+ Assert.assertEquals("Wrong errorId", "PendingRequest object is not of type 'RequestImpl.class'",
+ ((EaafException) protAuthService.getException()).getErrorId());
+
+ }
+
+ @Test
+ public void withOutRelayStateMissingPendingReq() throws IOException, EaafException, SpecificCommunicationException {
+ //set-up
+ String pendingReqId = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setPendingReqId(pendingReqId);
+ storage.storePendingRequest(pendingReq);
+
+ String inResponseTo = "_".concat(Random.nextHexRandom16());
+
+ Builder iLightResponse = new AuthenticationResponse.Builder();
+ iLightResponse.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(Constants.SUCCESS_URI)
+ .inResponseTo(inResponseTo)
+ .subjectNameIdFormat("afaf");
+
+ AuthenticationResponse eidasResp = iLightResponse.build();
+ BinaryLightToken token = connector.putResponse(eidasResp);
+ httpReq.setParameter(EidasParameterKeys.TOKEN.toString(),
+ Base64.getEncoder().encodeToString(token.getTokenBytes()));
+
+
+ //execute test
+ controller.restoreEidasAuthProcess(httpReq, httpResp);
+
+
+ //validate state
+ Assert.assertNull("eIDAS response", httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertNotNull("missing error", protAuthService.getException());
+ Assert.assertEquals("Wrong errorId", "auth.26",
+ ((EaafException) protAuthService.getException()).getErrorId());
+
+ }
+
+ @Test
+ public void withInResponseToElement() throws IOException, EaafException, SpecificCommunicationException {
+ //set-up
+ String pendingReqId = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setPendingReqId(pendingReqId);
+ storage.storePendingRequest(pendingReq);
+
+ String inResponseTo = "_".concat(Random.nextHexRandom16());
+ transStore.put(inResponseTo, pendingReqId, -1);
+
+ Builder iLightResponse = new AuthenticationResponse.Builder();
+ iLightResponse.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(Constants.SUCCESS_URI)
+ .inResponseTo(inResponseTo)
+ .subjectNameIdFormat("afaf");
+
+ AuthenticationResponse eidasResp = iLightResponse.build();
+ BinaryLightToken token = connector.putResponse(eidasResp);
+ httpReq.setParameter(EidasParameterKeys.TOKEN.toString(),
+ Base64.getEncoder().encodeToString(token.getTokenBytes()));
+
+
+ //execute test
+ controller.restoreEidasAuthProcess(httpReq, httpResp);
+
+
+ //validate state
+ Assert.assertNotNull("eIDAS response", httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertEquals("wrong eIDAS response", eidasResp,
+ httpReq.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE));
+
+ Assert.assertNotNull("missing error", protAuthService.getException());
+ Assert.assertEquals("Wrong errorId", "PendingRequest object is not of type 'RequestImpl.class'",
+ ((EaafException) protAuthService.getException()).getErrorId());
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java
new file mode 100644
index 00000000..4d9ae035
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java
@@ -0,0 +1,439 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.test;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchProviderException;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.ws.soap.SOAPFaultException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.binding.soap.SoapFault;
+import org.joda.time.DateTime;
+import org.jose4j.lang.JoseException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.Base64Utils;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.skjolber.mockito.soap.SoapServiceRule;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.exceptions.EaafParserException;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import szrservices.GetBPKFromStammzahlEncryptedResponse;
+import szrservices.GetBPKFromStammzahlEncryptedResponseType;
+import szrservices.GetIdentityLinkEidasResponse;
+import szrservices.IdentityLinkType;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SZRException_Exception;
+import szrservices.SignContentEntry;
+import szrservices.SignContentResponse;
+import szrservices.SignContentResponseType;
+import szrservices.TravelDocumentType;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public class SzrClientTest {
+ private static final Logger log = LoggerFactory.getLogger(SzrClientTest.class);
+
+ @Autowired SzrClient szrClient;
+ @Autowired MsConnectorDummyConfigMap basicConfig;
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ private static final String givenName = "Franz";
+ private static final String familyName = "Mustermann";
+ private static final String dateOfBirth = "1989-05-05";
+ private static final String eIDASeID = "IS/AT/1234sdgsdfg56789ABCDEF";
+ private static final String DUMMY_TARGET = EaafConstants.URN_PREFIX_CDID + "ZP";
+
+ private SZR szrMock = null;
+ ErnbEidData eidData = null;
+
+ @Rule
+ public SoapServiceRule soap = SoapServiceRule.newInstance();
+
+ /**
+ * Initialize jUnit test.
+ */
+ @Before
+ public void initializer() {
+ if (szrMock == null) {
+ szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr");
+
+ }
+
+ eidData = new ErnbEidData();
+ eidData.setFamilyName(familyName);
+ eidData.setGivenName(givenName);
+ eidData.setDateOfBirth(new DateTime());
+ eidData.setCitizenCountryCode("IS");
+ eidData.setPseudonym("1234sdgsdfg56789ABCDEF");
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.eidasbind.mds.inject", "false");
+
+ }
+
+
+
+
+ @Test
+ public void getStammzahlenEcryptedTest() throws JAXBException, SZRException_Exception, SzrCommunicationException {
+ final GetBPKFromStammzahlEncryptedResponse szrResponse = new GetBPKFromStammzahlEncryptedResponse();
+ final GetBPKFromStammzahlEncryptedResponseType result1 = new GetBPKFromStammzahlEncryptedResponseType();
+ szrResponse.getOut().add(result1);
+
+ result1.setKey(RandomStringUtils.randomAlphanumeric(20));
+
+ // when(szrMock.getBPKFromStammzahlEncrypted(anyList()))
+ // .thenReturn(Arrays.asList(result1));
+ when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(result1.getKey());
+
+ String stammzahlEncrypted = szrClient.getEncryptedStammzahl(new PersonInfoType());
+
+ Assert.assertEquals("bcBind not match", result1.getKey(), stammzahlEncrypted);
+
+ when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(null);
+ try {
+ stammzahlEncrypted = szrClient.getEncryptedStammzahl(new PersonInfoType());
+ } catch (SzrCommunicationException e) {
+ Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01"));
+ }
+ }
+
+ @Test
+ public void getEidasBindRealSzrResponse() throws SZRException_Exception, SzrCommunicationException, IOException {
+ final SignContentResponse szrResponse = new SignContentResponse();
+ final SignContentEntry result1 = new SignContentEntry();
+ final SignContentResponseType content = new SignContentResponseType();
+ content.getOut().add(result1);
+ szrResponse.setSignContentResponse(content);
+
+ result1.setKey("bcBindReq");
+ result1.setValue(IOUtils.toString(SzrClient.class.getResourceAsStream("/data/szr/signed_eidasBind.jws")));
+
+ when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content);
+
+ final String bcBind = szrClient
+ .getEidsaBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10),
+ RandomStringUtils.randomAlphabetic(10), eidData);
+
+ Assert.assertNotNull("bcBind is null", bcBind);
+ Assert.assertEquals("bcBind not match", result1.getValue(), bcBind);
+
+ }
+
+ @Test
+ public void eidasBindNull() throws SZRException_Exception {
+ when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(null);
+
+ try {
+ szrClient
+ .getEidsaBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10),
+ RandomStringUtils.randomAlphabetic(10), eidData);
+ } catch (SzrCommunicationException e) {
+ Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01"));
+
+ }
+ }
+
+ @Test
+ public void eidasBindInvalidResponse() throws SZRException_Exception {
+ final SignContentEntry result2 = new SignContentEntry();
+ final SignContentResponseType content1 = new SignContentResponseType();
+ content1.getOut().add(result2);
+ when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content1);
+
+ try {
+ szrClient
+ .getEidsaBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10),
+ RandomStringUtils.randomAlphabetic(10), eidData);
+ } catch (SzrCommunicationException e) {
+ Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01"));
+
+ }
+ }
+
+ public void eidasBindEmptyResponse() throws SZRException_Exception {
+ final SignContentEntry result2 = new SignContentEntry();
+ final SignContentResponseType content1 = new SignContentResponseType();
+ content1.getOut().add(result2);
+ result2.setKey("bcBindReq");
+ result2.setValue("");
+ when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content1);
+
+ try {
+ szrClient
+ .getEidsaBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10),
+ RandomStringUtils.randomAlphabetic(10), eidData);
+ } catch (SzrCommunicationException e) {
+ Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01"));
+
+ }
+ }
+
+ @Test
+ public void eidasBindValid() throws SZRException_Exception, SzrCommunicationException, JsonMappingException,
+ JsonProcessingException, JoseException {
+ final SignContentResponse szrResponse = new SignContentResponse();
+ final SignContentEntry result1 = new SignContentEntry();
+ final SignContentResponseType content = new SignContentResponseType();
+ content.getOut().add(result1);
+ szrResponse.setSignContentResponse(content);
+
+ result1.setKey("bcBindReq");
+ result1.setValue(RandomStringUtils.randomAlphanumeric(100));
+
+ when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content);
+
+ final String bcBind = szrClient
+ .getEidsaBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10),
+ RandomStringUtils.randomAlphabetic(10), eidData);
+
+ Assert.assertNotNull("bcBind is null", bcBind);
+ Assert.assertEquals("bcBind not match", result1.getValue(), bcBind);
+
+ }
+
+ @Test
+ public void eidasBindValidWithMds() throws SZRException_Exception, SzrCommunicationException, JoseException,
+ JsonMappingException, JsonProcessingException {
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.eidasbind.mds.inject", "true");
+
+ final SignContentResponse szrResponse = new SignContentResponse();
+ final SignContentEntry result1 = new SignContentEntry();
+ final SignContentResponseType content = new SignContentResponseType();
+ content.getOut().add(result1);
+ szrResponse.setSignContentResponse(content);
+
+ result1.setKey("bcBindReq");
+ result1.setValue(RandomStringUtils.randomAlphanumeric(100));
+
+ when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content);
+
+ final String bcBind = szrClient
+ .getEidsaBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10),
+ RandomStringUtils.randomAlphabetic(10), eidData);
+
+ Assert.assertNotNull("bcBind is null", bcBind);
+ Assert.assertEquals("bcBind not match", result1.getValue(), bcBind);
+
+ }
+
+ @Test
+ public void getIdentityLinkRawModeValidResponse()
+ throws SZRException_Exception, EaafParserException, NoSuchProviderException, IOException, InvalidKeyException,
+ EidasSAuthenticationException, JAXBException {
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");
+
+ try {
+ log.debug("Starting connecting SZR Gateway");
+ final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(getPersonInfo());
+
+ Assert.assertNotNull(result);
+ Assert.assertNotNull(result.getAssertion());
+
+ final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser((Element) result.getAssertion())
+ .parseIdentityLink();
+ Assert.assertNotNull(identityLink);
+
+ System.out.println(identityLink.getSerializedSamlAssertion());
+
+ checkElement("Mustermann", identityLink.getFamilyName());
+ checkElement("Hans", identityLink.getGivenName());
+ checkElement("1989-05-05", identityLink.getDateOfBirth());
+ checkElement("urn:publicid:gv.at:baseid", identityLink.getIdentificationType());
+ checkElement("k+zDM1BVpN1WJO4x7ZQ3ng==", identityLink.getIdentificationValue());
+ Assert.assertNotNull(identityLink.getSerializedSamlAssertion());
+ Assert.assertNotNull(identityLink.getSamlAssertion());
+
+ } catch (final SzrCommunicationException e) {
+ Assert.fail();
+
+ }
+
+ }
+
+ @Test
+ public void getIdentityLinkRawModeErrorTravelerDocExists()
+ throws SZRException_Exception, EaafParserException, NoSuchProviderException, IOException, InvalidKeyException,
+ EidasSAuthenticationException, JAXBException, ParserConfigurationException, SAXException {
+ setSzrExceptionIdentityLink("/data/szr/szr_resp_error_travelerdocexists.xml");
+
+ try {
+ log.debug("Starting connecting SZR Gateway");
+ szrClient.getIdentityLinkInRawMode(getPersonInfo());
+ Assert.fail();
+
+ } catch (final SzrCommunicationException e) {
+ checkElement("ernb.02", e.getErrorId());
+ Assert.assertNotNull(e.getCause());
+ org.springframework.util.Assert.isInstanceOf(SOAPFaultException.class, e.getCause());
+ Assert.assertNotNull(((SOAPFaultException) e.getCause()).getFault());
+ checkElement("p344:F455", ((SOAPFaultException) e.getCause()).getFault().getFaultCode());
+ checkElement(
+ "The travel document you sent to insert a person already exists for another person. " + "Either check the document or have the person altered accordingly",
+ ((SOAPFaultException) e.getCause()).getFault().getFaultString());
+
+ }
+
+ }
+
+ @Ignore
+ @Test
+ public void getBpkTest() throws SZRException_Exception, EidasSAuthenticationException {
+ final List<String> bPK = szrClient.getBpk(getPersonInfo(), DUMMY_TARGET, basicConfig
+ .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, "no VKZ defined"));
+
+ if (bPK.isEmpty()) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"bPK list is empty"});
+ }
+ for (final String b : bPK) {
+ if (StringUtils.isEmpty(b)) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"bPK is null or empty"});
+ }
+ }
+
+ }
+
+ private void checkElement(String expected, String value) {
+ Assert.assertNotNull(value);
+ Assert.assertEquals(expected, value);
+
+ }
+
+ private void setSzrResponseIdentityLink(String responseXmlPath) throws JAXBException, SZRException_Exception {
+ final JAXBContext jaxbContext = JAXBContext
+ .newInstance(szrservices.ObjectFactory.class, org.w3._2001._04.xmldsig_more.ObjectFactory.class,
+ org.w3._2000._09.xmldsig.ObjectFactory.class,
+ at.gv.e_government.reference.namespace.persondata._20020228.ObjectFactory.class);
+ final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ final GetIdentityLinkEidasResponse szrResponse = (GetIdentityLinkEidasResponse) jaxbUnmarshaller
+ .unmarshal(this.getClass().getResourceAsStream(responseXmlPath));
+ when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenReturn(szrResponse.getGetIdentityLinkReturn());
+
+ }
+
+ private void setSzrExceptionIdentityLink(String responseXmlPath)
+ throws JAXBException, ParserConfigurationException, SAXException, IOException, SZRException_Exception {
+ final Element detailerror = DomUtils.parseXmlNonValidating(this.getClass().getResourceAsStream(responseXmlPath));
+ final javax.xml.namespace.QName qName = new javax.xml.namespace.QName("urn:SZRServices", "F455", "p344");
+ final SoapFault fault = new SoapFault(
+ "The travel document you sent to insert a person already exists for another person. " + "Either check the document or have the person altered accordingly",
+ qName);
+ fault.setRole("urn:SZRServices");
+ fault.setDetail(detailerror);
+ when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenThrow(fault);
+
+ }
+
+ private String createHashFromUniqueId(String uniqueId) throws EidasSAuthenticationException {
+ try {
+ final MessageDigest md = MessageDigest.getInstance("SHA-256");
+ final byte[] hash = md.digest(uniqueId.getBytes("UTF-8"));
+ final String hashBase64 = new String(Base64Utils.encode(hash), "UTF-8").replaceAll("\r\n", "");
+ return hashBase64;
+
+ } catch (final Exception ex) {
+ throw new EidasSAuthenticationException("internal.03", new Object[]{}, ex);
+
+ }
+ }
+
+ private PersonInfoType getPersonInfo() throws EidasSAuthenticationException {
+ final PersonInfoType personInfo = new PersonInfoType();
+ final PersonNameType personName = new PersonNameType();
+ final PhysicalPersonType naturalPerson = new PhysicalPersonType();
+ final TravelDocumentType eDocument = new TravelDocumentType();
+
+ naturalPerson.setName(personName);
+ personInfo.setPerson(naturalPerson);
+ personInfo.setTravelDocument(eDocument);
+
+ // parse some eID attributes
+ final Triple<String, String, String> eIdentifier = EidasResponseUtils.parseEidasPersonalIdentifier(eIDASeID);
+ final String uniqueId = createHashFromUniqueId(eIdentifier.getThird());
+ final String citizenCountry = eIdentifier.getFirst();
+
+ // person information
+ personName.setFamilyName(familyName);
+ personName.setGivenName(givenName);
+ naturalPerson.setDateOfBirth(dateOfBirth);
+ eDocument.setIssuingCountry(citizenCountry);
+ eDocument.setDocumentNumber(uniqueId);
+
+ // eID document information
+ eDocument.setDocumentType(basicConfig
+ .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE,
+ Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE));
+
+ return personInfo;
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java
new file mode 100644
index 00000000..1e7ff369
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java
@@ -0,0 +1,236 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.test;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchProviderException;
+import java.util.List;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.bouncycastle.util.encoders.Base64;
+import org.joda.time.DateTime;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.IfProfileValue;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.Base64Utils;
+import org.w3c.dom.Element;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.exceptions.EaafParserException;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
+import szrservices.IdentityLinkType;
+import szrservices.PersonInfoType;
+import szrservices.SZRException_Exception;
+import szrservices.TravelDocumentType;
+
+
+@IfProfileValue(name = "spring.profiles.active", value = "devEnvironment")
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_realConfig.xml"})
+@TestPropertySource(locations = {
+ //"classpath:/application.properties",
+ "file:/home/tlenz/Projekte/config/ms_connector/default_config.properties",
+ })
+public class SzrClientTestProduction {
+ private static final Logger log = LoggerFactory.getLogger(SzrClientTestProduction.class);
+
+ @Autowired
+ SzrClient szrClient;
+ @Autowired
+ IConfiguration basicConfig;
+
+ private static final String givenName = "Franz";
+ private static final String familyName = "Mustermann";
+ // private static final String dateOfBirth = "1989-05-05";
+ private static final String dateOfBirth = "1989-05-04";
+ private static final String eIDASeID = "IS/AT/1234ffgsdfg56789ABCDEF";
+
+ private static final String DUMMY_TARGET = EaafConstants.URN_PREFIX_CDID + "ZP";
+
+ @Test
+ public void dummyTest() {
+
+ }
+
+ @Test
+ public void getVsz() throws SzrCommunicationException, EidasSAuthenticationException {
+ String vsz = szrClient.getEncryptedStammzahl(getPersonInfo());
+ Assert.assertNotNull("vsz", vsz);
+
+ }
+
+ @Test
+ public void getEidasBind() throws SzrCommunicationException, EidasSAuthenticationException {
+ String vsz = RandomStringUtils.randomAlphanumeric(10);
+ String bindingPubKey = Base64.toBase64String(RandomStringUtils.random(20).getBytes());
+ String eidStatus = "urn:eidgvat:eid.status.eidas";
+ ErnbEidData eidData = new ErnbEidData();
+ eidData.setFamilyName(familyName);
+ eidData.setGivenName(givenName);
+ eidData.setDateOfBirth(new DateTime());
+ eidData.setCitizenCountryCode("IS");
+ eidData.setPseudonym("1234sdgsdfg56789ABCDEF");
+
+
+ String eidasBind = szrClient.getEidsaBind(vsz, bindingPubKey, eidStatus, eidData);
+
+ Assert.assertNotNull("eidasBind", eidasBind);
+
+ }
+
+
+ @Test
+ public void getIdentityLinkRawMode() throws SZRException_Exception, EaafParserException,
+ NoSuchProviderException, IOException, InvalidKeyException, EidasSAuthenticationException {
+ log.debug("Starting connecting SZR Gateway");
+ final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(
+ getPersonInfo());
+
+ final Element idlFromSzr = (Element) result.getAssertion();
+ final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink();
+
+ if (identityLink == null) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO IDL object" });
+ }
+
+ System.out.println(identityLink.getSerializedSamlAssertion());
+
+ if (StringUtils.isEmpty(identityLink.getFamilyName())) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO FamilyName from IDL" });
+ }
+
+ if (StringUtils.isEmpty(identityLink.getGivenName())) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO GivenName from IDL" });
+ }
+
+ if (StringUtils.isEmpty(identityLink.getDateOfBirth())) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO DateOfBirthName from IDL" });
+ }
+
+ if (StringUtils.isEmpty(identityLink.getIdentificationType())) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO baseIdType from IDL" });
+ }
+
+ if (StringUtils.isEmpty(identityLink.getIdentificationValue())) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO baseId from IDL" });
+ }
+
+ if (StringUtils.isEmpty(identityLink.getSerializedSamlAssertion())) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO serialized IDL" });
+ }
+
+ if (identityLink.getSamlAssertion() == null) {
+ throw new SzrCommunicationException("ernb.00", new Object[] { "NO raw IDL" });
+ }
+
+ }
+
+
+ @Ignore
+ @Test
+ public void getBpkTest() throws SZRException_Exception, EidasSAuthenticationException {
+ final List<String> bPK = szrClient.getBpk(getPersonInfo(), DUMMY_TARGET,
+ basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ,
+ "no VKZ defined"));
+
+ if (bPK.isEmpty()) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"bPK list is empty"});
+ }
+ for (String b : bPK) {
+ if (StringUtils.isEmpty(b)) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"bPK is null or empty"});
+ }
+ }
+
+ }
+
+ private String createHashFromUniqueId(String uniqueId) throws EidasSAuthenticationException {
+ try {
+ final MessageDigest md = MessageDigest.getInstance("SHA-256");
+ final byte[] hash = md.digest(uniqueId.getBytes("UTF-8"));
+ final String hashBase64 = new String(Base64Utils.encode(hash), "UTF-8").replaceAll("\r\n", "");
+ return hashBase64;
+
+ } catch (final Exception ex) {
+ throw new EidasSAuthenticationException("internal.03", new Object[] {}, ex);
+
+ }
+ }
+
+ private PersonInfoType getPersonInfo() throws EidasSAuthenticationException {
+ final PersonInfoType personInfo = new PersonInfoType();
+ final PersonNameType personName = new PersonNameType();
+ final PhysicalPersonType naturalPerson = new PhysicalPersonType();
+ final TravelDocumentType eDocument = new TravelDocumentType();
+
+ naturalPerson.setName(personName);
+ personInfo.setPerson(naturalPerson);
+ personInfo.setTravelDocument(eDocument);
+
+ // parse some eID attributes
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier(eIDASeID);
+ final String uniqueId = createHashFromUniqueId(eIdentifier.getThird());
+ final String citizenCountry = eIdentifier.getFirst();
+
+ // person information
+ personName.setFamilyName(familyName);
+ personName.setGivenName(givenName);
+ naturalPerson.setDateOfBirth(dateOfBirth);
+ eDocument.setIssuingCountry(citizenCountry);
+ eDocument.setDocumentNumber(uniqueId);
+
+ // eID document information
+ eDocument.setDocumentType(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE,
+ Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE));
+
+ return personInfo;
+ }
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/dummy/DummySpecificCommunicationService.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/dummy/DummySpecificCommunicationService.java
new file mode 100644
index 00000000..78294047
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/dummy/DummySpecificCommunicationService.java
@@ -0,0 +1,66 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy;
+
+import java.util.Collection;
+
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.tx.BinaryLightToken;
+import eu.eidas.specificcommunication.BinaryLightTokenHelper;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+import lombok.Setter;
+
+public class DummySpecificCommunicationService implements SpecificCommunicationService {
+
+ private ILightRequest lightRequest;
+ private ILightResponse lightResponse;
+
+ @Setter
+ private SpecificCommunicationException error;
+
+ @Override
+ public BinaryLightToken putRequest(ILightRequest lightRequest) throws SpecificCommunicationException {
+ this.lightRequest = lightRequest;
+ return BinaryLightTokenHelper.createBinaryLightToken("Test", "TestSecret", "SHA-256");
+ }
+
+ @Override
+ public ILightRequest getAndRemoveRequest(String tokenBase64, Collection<AttributeDefinition<?>> registry)
+ throws SpecificCommunicationException {
+ if (error != null) {
+ throw error;
+
+ }
+ return lightRequest;
+ }
+
+ @Override
+ public BinaryLightToken putResponse(ILightResponse lightResponse) throws SpecificCommunicationException {
+ this.lightResponse = lightResponse;
+ return BinaryLightTokenHelper.createBinaryLightToken("Test", "TestSecret", "SHA-256");
+ }
+
+ @Override
+ public ILightResponse getAndRemoveResponse(String tokenBase64, Collection<AttributeDefinition<?>> registry)
+ throws SpecificCommunicationException {
+ return lightResponse;
+ }
+
+ public ILightRequest getiLightRequest() {
+ return lightRequest;
+ }
+
+ public void setiLightRequest(ILightRequest lightReques) {
+ this.lightRequest = lightReques;
+ }
+
+ public ILightResponse getiLightResponse() {
+ return lightResponse;
+ }
+
+ public void setiLightResponse(ILightResponse lightResponse) {
+ this.lightResponse = lightResponse;
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java
new file mode 100644
index 00000000..e1a29137
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java
@@ -0,0 +1,491 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import java.net.URISyntaxException;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jose4j.jwa.AlgorithmConstraints;
+import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
+import org.jose4j.jws.AlgorithmIdentifiers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.skjolber.mockito.soap.SoapServiceRule;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils.JwsResult;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+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.data.Pair;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap.Builder;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import lombok.val;
+import szrservices.JwsHeaderParam;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SignContentEntry;
+import szrservices.SignContentResponseType;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+public class CreateIdentityLinkTaskEidNewTest {
+
+ @Autowired(required = true)
+ private CreateIdentityLinkTask task;
+
+ @Autowired(required = true)
+ private MsConnectorDummyConfigMap basicConfig;
+ @Autowired
+ protected EidasAttributeRegistry attrRegistry;
+
+ @Autowired
+ EaafKeyStoreFactory keyStoreFactory;
+
+ @Autowired
+ private IRequestStorage requestStorage;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+ private DummySpConfiguration oaParam;
+ private SZR szrMock;
+
+ private static final String PW = "f/+saJBc3a}*/T^s";
+ private static final String ALIAS = "connectorkeypair";
+
+ private static final List<String> BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList(Arrays
+ .asList(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256,
+ AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512, AlgorithmIdentifiers.RSA_PSS_USING_SHA256,
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA512));
+
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ private AuthenticationResponse response;
+
+ @Rule
+ public final SoapServiceRule soap = SoapServiceRule.newInstance();
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+ pendingReq = new TestRequestImpl();
+
+ response = buildDummyAuthResponse(false);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+
+
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+ pendingReq.setTransactionId("avaasbav");
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "XX");
+ executionContext.put(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT, true);
+
+ szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr");
+ }
+
+ @Test
+ public void successfulProcessWithDeInfos() throws Exception {
+ //initialize test
+ response = buildDummyAuthResponse(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+
+ String vsz = RandomStringUtils.randomNumeric(10);
+ when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(vsz);
+ val signContentResp = new SignContentResponseType();
+ final SignContentEntry signContentEntry = new SignContentEntry();
+ signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10));
+ signContentResp.getOut().add(signContentEntry);
+ when(szrMock, "signContent", any(), any(), any()).thenReturn(signContentResp);
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNotNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNotNull("AuthBlock", authBlock);
+
+ Assert.assertTrue("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+
+ // check authblock signature
+ final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT,
+ BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()]));
+ Pair<KeyStore, Provider> keyStore = getKeyStore();
+ X509Certificate[] trustedCerts = EaafKeyStoreUtils
+ .getPrivateKeyAndCertificates(keyStore.getFirst(), ALIAS, PW.toCharArray(), true, "junit").getSecond();
+ JwsResult result = JoseUtils.validateSignature(authBlock, Arrays.asList(trustedCerts), constraints);
+ Assert.assertTrue("AuthBlock not valid", result.isValid());
+ JsonNode authBlockJson = mapper.readTree(result.getPayLoad());
+ Assert.assertNotNull("deserialized AuthBlock", authBlockJson);
+
+ Assert.assertNotNull("no piiTransactionId in pendingRequesdt",
+ storedPendingReq.getUniquePiiTransactionIdentifier());
+ Assert.assertEquals("piiTransactionId", storedPendingReq.getUniquePiiTransactionIdentifier(),
+ authBlockJson.get("piiTransactionId").asText());
+ Assert.assertEquals("appId", randomTestSp, authBlockJson.get("appId").asText());
+ Assert.assertFalse("'challenge' is null", authBlockJson.get("challenge").asText().isEmpty());
+ Assert.assertFalse("'timestamp' is null", authBlockJson.get("timestamp").asText().isEmpty());
+ Assert.assertFalse("binding pubKey", authBlockJson.has("bindingPublicKey"));
+
+
+ // check vsz request
+ ArgumentCaptor<PersonInfoType> argument4 = ArgumentCaptor.forClass(PersonInfoType.class);
+ ArgumentCaptor<Boolean> argument5 = ArgumentCaptor.forClass(Boolean.class);
+ verify(szrMock, times(1)).getStammzahlEncrypted(argument4.capture(), argument5.capture());
+
+ Boolean param5 = argument5.getValue();
+ Assert.assertTrue("insertERnP flag", param5);
+ PersonInfoType person = argument4.getValue();
+ Assert.assertEquals("FamilyName",
+ response.getAttributes().getAttributeValuesByFriendlyName("FamilyName").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("FamilyName").iterator().next()),
+ person.getPerson().getName().getFamilyName());
+ Assert.assertEquals("GivenName",
+ response.getAttributes().getAttributeValuesByFriendlyName("FirstName").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("FirstName").iterator().next()),
+ person.getPerson().getName().getGivenName());
+ Assert.assertEquals("DateOfBirth",
+ response.getAttributes().getAttributeValuesByFriendlyName("DateOfBirth").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("DateOfBirth").iterator().next())
+ .toString().split("T")[0],
+ person.getPerson().getDateOfBirth());
+
+ Assert.assertEquals("PlaceOfBirth",
+ response.getAttributes().getAttributeValuesByFriendlyName("PlaceOfBirth").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("PlaceOfBirth").iterator().next()),
+ person.getPerson().getPlaceOfBirth());
+ Assert.assertEquals("BirthName",
+ response.getAttributes().getAttributeValuesByFriendlyName("BirthName").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("BirthName").iterator().next()),
+ person.getPerson().getAlternativeName().getFamilyName());
+
+ Assert.assertEquals("CitizenCountry", "LU", person.getTravelDocument().getIssuingCountry());
+ Assert.assertEquals("DocumentType", "ELEKTR_DOKUMENT", person.getTravelDocument().getDocumentType());
+
+ Assert.assertEquals("Identifier",
+ response.getAttributes().getAttributeValuesByFriendlyName("PersonIdentifier").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("PersonIdentifier").iterator().next())
+ .toString().split("/")[2],
+ person.getTravelDocument().getDocumentNumber());
+
+ // check bcBind singing request
+ ArgumentCaptor<Boolean> argument1 = ArgumentCaptor.forClass(Boolean.class);
+ ArgumentCaptor<List<JwsHeaderParam>> argument2 = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<List<SignContentEntry>> argument3 = ArgumentCaptor.forClass(List.class);
+ verify(szrMock, times(1)).signContent(argument1.capture(), argument2.capture(), argument3.capture());
+ Boolean param1 = argument1.getValue();
+ Assert.assertFalse("addCert flag", param1);
+
+ List<JwsHeaderParam> param2 = argument2.getValue();
+ Assert.assertNotNull("JWS Headers", param2);
+ Assert.assertFalse("JWS Headers empty", param2.isEmpty());
+ Assert.assertEquals("Wrong JWS header size", 1, param2.size());
+ Assert.assertEquals("Missing JWS header key", "urn:at.gv.eid:bindtype", param2.get(0).getKey());
+ Assert.assertEquals("Missing JWS header value", "urn:at.gv.eid:eidasBind", param2.get(0).getValue());
+
+ List<SignContentEntry> param3 = argument3.getValue();
+ Assert.assertNotNull("sign Payload", param3);
+ Assert.assertEquals("wrong sign-payload size", 1, param3.size());
+ Assert.assertNotNull("payload", param3.get(0).getValue().getBytes());
+ JsonNode bcBind = mapper.readTree(param3.get(0).getValue().getBytes());
+ Assert.assertNotNull("bcbind req", bcBind);
+
+ Assert.assertEquals("vsz", vsz, bcBind.get("urn:eidgvat:attributes.vsz.value").asText());
+ Assert.assertEquals("eid status", "urn:eidgvat:eid.status.eidas",
+ bcBind.get("urn:eidgvat:attributes.eid.status").asText());
+ Assert.assertTrue("pubKeys", bcBind.has("urn:eidgvat:attributes.user.pubkeys"));
+ Assert.assertTrue("pubKeys", bcBind.get("urn:eidgvat:attributes.user.pubkeys").isArray());
+ Iterator<JsonNode> pubKeys = bcBind.get("urn:eidgvat:attributes.user.pubkeys").elements();
+ Assert.assertTrue("No PubKey", pubKeys.hasNext());
+ Assert.assertEquals("Wrong pubKey",
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmxcB5jnrAwGn7xjgVFv1UBUv1pluwDRFQx7x5O6rSn7pblYfwaWeKa8y"
+ + "jS5BDDaZ00mhhnSlm2XByNrkg5yBGetTgBGtQVAxV5apfuAWN8TS3uSXgdZol7Khd6kraUITtnulvLe8tNaboom5P0zN6UxbJN"
+ + "NVLishVp80HiRXiDbplCTUk8b5cYtmivdb0+5JBTa7L5N/anRVnHHoJCXgNPTouO8daUHZbG1mPk0HgqD8rhZ+OBzE+APKH9No"
+ + "agedSrGRDLdIgZxkrg0mxmfsZQIi2wdJSi3y0PAjEps/s4j0nmw9bPRgCMNLBqqjxtN5JKC8E1yyLm7YefXv/nPaMwIDAQAB",
+ pubKeys.next().asText());
+ Assert.assertFalse("More than one PubKey", pubKeys.hasNext());
+
+ }
+
+ @Test
+ public void successfulProcessWithStandardInfos() throws Exception {
+ //initialize test
+ String vsz = RandomStringUtils.randomNumeric(10);
+ when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(vsz);
+ val signContentResp = new SignContentResponseType();
+ final SignContentEntry signContentEntry = new SignContentEntry();
+ signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10));
+ signContentResp.getOut().add(signContentEntry);
+ when(szrMock, "signContent", any(), any(), any()).thenReturn(signContentResp);
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ String bindingPubKey = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME, bindingPubKey);
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNotNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ // check authblock signature
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNotNull("AuthBlock", authBlock);
+ final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT,
+ BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()]));
+ Pair<KeyStore, Provider> keyStore = getKeyStore();
+ X509Certificate[] trustedCerts = EaafKeyStoreUtils
+ .getPrivateKeyAndCertificates(keyStore.getFirst(), ALIAS, PW.toCharArray(), true, "junit").getSecond();
+ JwsResult result = JoseUtils.validateSignature(authBlock, Arrays.asList(trustedCerts), constraints);
+ Assert.assertTrue("AuthBlock not valid", result.isValid());
+ JsonNode authBlockJson = mapper.readTree(result.getPayLoad());
+ Assert.assertNotNull("deserialized AuthBlock", authBlockJson);
+
+ Assert.assertNotNull("no piiTransactionId in pendingRequesdt",
+ storedPendingReq.getUniquePiiTransactionIdentifier());
+ Assert.assertEquals("piiTransactionId", storedPendingReq.getUniquePiiTransactionIdentifier(),
+ authBlockJson.get("piiTransactionId").asText());
+ Assert.assertEquals("appId", randomTestSp, authBlockJson.get("appId").asText());
+ Assert.assertFalse("'challenge' is null", authBlockJson.get("challenge").asText().isEmpty());
+ Assert.assertFalse("'timestamp' is null", authBlockJson.get("timestamp").asText().isEmpty());
+ Assert.assertTrue("binding pubKey", authBlockJson.has("bindingPublicKey"));
+ Assert.assertEquals("binding PubKey", bindingPubKey, authBlockJson.get("bindingPublicKey").asText());
+
+ Assert.assertTrue("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+ // check vsz request
+ ArgumentCaptor<PersonInfoType> argument4 = ArgumentCaptor.forClass(PersonInfoType.class);
+ ArgumentCaptor<Boolean> argument5 = ArgumentCaptor.forClass(Boolean.class);
+ verify(szrMock, times(1)).getStammzahlEncrypted(argument4.capture(), argument5.capture());
+
+ Boolean param5 = argument5.getValue();
+ Assert.assertTrue("insertERnP flag", param5);
+ PersonInfoType person = argument4.getValue();
+ Assert.assertEquals("FamilyName",
+ response.getAttributes().getAttributeValuesByFriendlyName("FamilyName").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("FamilyName").iterator().next()),
+ person.getPerson().getName().getFamilyName());
+ Assert.assertEquals("GivenName",
+ response.getAttributes().getAttributeValuesByFriendlyName("FirstName").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("FirstName").iterator().next()),
+ person.getPerson().getName().getGivenName());
+ Assert.assertEquals("DateOfBirth",
+ response.getAttributes().getAttributeValuesByFriendlyName("DateOfBirth").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("DateOfBirth").iterator().next())
+ .toString().split("T")[0],
+ person.getPerson().getDateOfBirth());
+
+ Assert.assertNull("PlaceOfBirth", person.getPerson().getPlaceOfBirth());
+ Assert.assertNull("BirthName", person.getPerson().getAlternativeName());
+
+ Assert.assertEquals("CitizenCountry", "LU", person.getTravelDocument().getIssuingCountry());
+ Assert.assertEquals("DocumentType", "ELEKTR_DOKUMENT", person.getTravelDocument().getDocumentType());
+
+ Assert.assertEquals("Identifier",
+ response.getAttributes().getAttributeValuesByFriendlyName("PersonIdentifier").getFirstValue(
+ response.getAttributes().getDefinitionsByFriendlyName("PersonIdentifier").iterator().next())
+ .toString().split("/")[2],
+ person.getTravelDocument().getDocumentNumber());
+
+
+ }
+
+ @Test
+ public void getStammzahlEncryptedExceptionTest() throws Exception {
+ try {
+ when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(null);
+ task.execute(pendingReq, executionContext);
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("Incorrect exception thrown", e.getMessage(),
+ "IdentityLink generation for foreign person " + "FAILED.");
+ Assert.assertEquals("Incorrect exception thrown", ((SzrCommunicationException) e.getCause()).getErrorId(),
+ "ernb.01");
+ Assert.assertTrue("Incorrect exception thrown", e.getCause().getMessage().contains("Stammzahl response empty"));
+ }
+ }
+
+ @Test
+ public void signContentExceptionTest() throws Exception {
+ try {
+ when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(RandomStringUtils.randomNumeric(10));
+ when(szrMock, "signContent", any(), any(), any()).thenReturn(null);
+ task.execute(pendingReq, executionContext);
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("Incorrect exception thrown", e.getMessage(),
+ "IdentityLink generation for foreign person " + "FAILED.");
+ Assert.assertEquals("Incorrect exception thrown", ((SzrCommunicationException) e.getCause()).getErrorId(),
+ "ernb.01");
+ Assert.assertTrue("Incorrect exception thrown", e.getCause().getMessage().contains("BcBind response empty"));
+ }
+ }
+
+ private Pair<KeyStore, Provider> getKeyStore() throws EaafException {
+ // read Connector wide config data TODO connector wide!
+ String keyStoreName = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME);
+ String keyStorePw = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD);
+ String keyStorePath = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH);
+ String keyStoreType = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE);
+
+
+ //build new KeyStore configuration
+ KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration();
+ keyStoreConfiguration.setFriendlyName("jUnit test");
+
+ keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath);
+ keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw);
+ keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType));
+ keyStoreConfiguration.setKeyStoreName(keyStoreName);
+
+ //build new KeyStore based on configuration
+ return keyStoreFactory.buildNewKeyStore(keyStoreConfiguration);
+
+ }
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponse(boolean withAll) throws URISyntaxException {
+ final AttributeDefinition attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+ final AttributeDefinition attributeDef5 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PLACEOFBIRTH).first();
+ final AttributeDefinition attributeDef6 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_BIRTHNAME).first();
+
+ final Builder attributeMap = ImmutableAttributeMap.builder();
+ attributeMap.put(attributeDef, "LU/AT/" + RandomStringUtils.randomNumeric(64));
+ attributeMap.put(attributeDef2, RandomStringUtils.randomAlphabetic(10));
+ attributeMap.put(attributeDef3, RandomStringUtils.randomAlphabetic(10));
+ attributeMap.put(attributeDef4, "2001-01-01");
+ if (withAll) {
+ attributeMap.put(attributeDef5, RandomStringUtils.randomAlphabetic(10));
+ attributeMap.put(attributeDef6, RandomStringUtils.randomAlphabetic(10));
+
+ }
+
+ val b = new AuthenticationResponse.Builder();
+ return b.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(Constants.SUCCESS_URI)
+ .inResponseTo("_".concat(Random.nextHexRandom16()))
+ .subjectNameIdFormat("afaf")
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_PREFIX + RandomStringUtils.randomAlphabetic(5))
+ .attributes(attributeMap.build())
+ .build();
+ }
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java
new file mode 100644
index 00000000..d6485158
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java
@@ -0,0 +1,464 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.mockito.ArgumentMatchers.any;
+
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.github.skjolber.mockito.soap.SoapServiceRule;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import lombok.val;
+import szrservices.GetBPK;
+import szrservices.GetBPKResponse;
+import szrservices.GetIdentityLinkEidasResponse;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SZRException_Exception;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+public class CreateIdentityLinkTaskTest {
+
+ @Autowired(required = true)
+ private CreateIdentityLinkTask task;
+
+ @Autowired(required = true)
+ private MsConnectorDummyConfigMap basicConfig;
+ @Autowired
+ protected EidasAttributeRegistry attrRegistry;
+
+ @Autowired
+ EaafKeyStoreFactory keyStoreFactory;
+
+ @Autowired
+ private IRequestStorage requestStorage;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+ private DummySpConfiguration oaParam;
+ private SZR szrMock;
+
+ private AuthenticationResponse response;
+ private Map<String, String> spConfig;
+
+ @Rule
+ public final SoapServiceRule soap = SoapServiceRule.newInstance();
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation", "false");
+
+ spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "false");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+ pendingReq = new TestRequestImpl();
+
+ response = buildDummyAuthResponse();
+
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+ pendingReq.setTransactionId("avaasbav");
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "XX");
+ executionContext.put(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT, true);
+
+ szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr");
+ }
+
+
+ @Test
+ public void buildIdentityLink() throws Exception {
+ //initialize test
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNull("AuthBlock", authBlock);
+
+ Assert.assertFalse("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+ Assert.assertNotNull("IDL", authProcessData.getIdentityLink());
+ checkElement("Mustermann", authProcessData.getIdentityLink().getFamilyName());
+ checkElement("Hans", authProcessData.getIdentityLink().getGivenName());
+ checkElement("1989-05-05", authProcessData.getIdentityLink().getDateOfBirth());
+ checkElement("urn:publicid:gv.at:baseid", authProcessData.getIdentityLink().getIdentificationType());
+ checkElement("k+zDM1BVpN1WJO4x7ZQ3ng==", authProcessData.getIdentityLink().getIdentificationValue());
+ Assert.assertNotNull(authProcessData.getIdentityLink().getSerializedSamlAssertion());
+ Assert.assertNotNull(authProcessData.getIdentityLink().getSamlAssertion());
+
+ Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+ Assert.assertEquals("wrong bPK", "XX:FkXtOaSSeR3elyL9KLLvijIYDMU=",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+
+ }
+
+ @Test
+ public void buildIdentityLinkWithWbpk() throws Exception {
+ //initialize test
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");
+ spConfig.put("target", EaafConstants.URN_PREFIX_WBPK + "FN+123456i");
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true");
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNull("AuthBlock", authBlock);
+
+ Assert.assertFalse("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+ Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+ Assert.assertEquals("wrong bPK", "FN+123456i:D26vJncPS2W790RH/LP04V+vNOQ=",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+
+ }
+
+ @Test
+ public void buildIdentityLinkWithEidasBpk() throws Exception {
+ //initialize test
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_2.xml");
+ spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EU");
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true");
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNull("AuthBlock", authBlock);
+
+ Assert.assertFalse("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+ Assert.assertNotNull("IDL", authProcessData.getIdentityLink());
+ checkElement("Musterfrau", authProcessData.getIdentityLink().getFamilyName());
+ checkElement("Martina", authProcessData.getIdentityLink().getGivenName());
+ checkElement("1991-04-15", authProcessData.getIdentityLink().getDateOfBirth());
+ checkElement("urn:publicid:gv.at:baseid", authProcessData.getIdentityLink().getIdentificationType());
+ checkElement("k+zDM1BV1312312332x7ZQ3ng==", authProcessData.getIdentityLink().getIdentificationValue());
+
+ Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+ Assert.assertEquals("wrong bPK", "AT+EU:AT/EU/1+wqDl059/02Ptny0g+LyuLDJV0=",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+
+ }
+
+ @Test
+ public void buildIdentityLinkWithUnknownBpk() throws Exception {
+ //initialize test
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");
+ spConfig.put("target", "urn:notextis:1234");
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true");
+
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("unknown bPKType not detected");
+
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("ErrorId", "builder.33",
+ ((EaafException) e.getOriginalException()).getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException())
+ .getParams().length);
+
+ }
+ }
+
+ @Test
+ public void noBpkResult() throws Exception {
+ //initialize test
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");
+ GetBPKResponse getBpkResp = new GetBPKResponse();
+ org.mockito.Mockito.when(szrMock.getBPK(any(GetBPK.class))).thenReturn(getBpkResp );
+
+ spConfig.put("target", "urn:notextis:1234");
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation", "true");
+
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("unknown bPKType not detected");
+
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("ErrorId", "ernb.01",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+ }
+
+ @Test
+ public void bPKFromSzr() throws Exception {
+ //initialize test
+ setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");
+ String bpk = RandomStringUtils.randomAlphanumeric(10);
+ GetBPKResponse getBpkResp = new GetBPKResponse();
+ getBpkResp.getGetBPKReturn().add(bpk);
+ org.mockito.Mockito.when(szrMock.getBPK(any(GetBPK.class))).thenReturn(getBpkResp );
+
+ spConfig.put("target", "urn:notextis:1234");
+
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation", "true");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNull("AuthBlock", authBlock);
+
+ Assert.assertFalse("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+ Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+ Assert.assertEquals("wrong bPK", bpk,
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));
+ }
+
+ @Test
+ public void buildDummyIdl() throws Exception {
+ //initialize test
+ String randomTestSp = RandomStringUtils.randomAlphabetic(10);
+ pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp);
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "true");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+
+ //validate state
+ // check if pendingRequest was stored
+ IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedPendingReq);
+
+ //check data in session
+ final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertNotNull("AuthProcessData", authProcessData);
+ Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ String authBlock = authProcessData.getGenericDataFromSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ Assert.assertNull("AuthBlock", authBlock);
+
+ Assert.assertFalse("EID process", authProcessData.isEidProcess());
+ Assert.assertTrue("foreigner process", authProcessData.isForeigner());
+ Assert.assertEquals("EID-ISSUING_NATION", "LU",
+ authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class));
+ Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel());
+ Assert.assertEquals("LoA", response.getLevelOfAssurance(),
+ authProcessData.getQaaLevel());
+
+ Assert.assertNotNull("IDL", authProcessData.getIdentityLink());
+
+ }
+
+ private void setSzrResponseIdentityLink(String responseXmlPath) throws JAXBException, SZRException_Exception {
+ final JAXBContext jaxbContext = JAXBContext
+ .newInstance(szrservices.ObjectFactory.class, org.w3._2001._04.xmldsig_more.ObjectFactory.class,
+ org.w3._2000._09.xmldsig.ObjectFactory.class,
+ at.gv.e_government.reference.namespace.persondata._20020228.ObjectFactory.class);
+ final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ final GetIdentityLinkEidasResponse szrResponse = (GetIdentityLinkEidasResponse) jaxbUnmarshaller
+ .unmarshal(this.getClass().getResourceAsStream(responseXmlPath));
+ org.mockito.Mockito.when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenReturn(szrResponse.getGetIdentityLinkReturn());
+
+ }
+ private void checkElement(String expected, String value) {
+ Assert.assertNotNull(value);
+ Assert.assertEquals(expected, value);
+
+ }
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponse() throws URISyntaxException {
+ final AttributeDefinition attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+
+ final ImmutableAttributeMap attributeMap = ImmutableAttributeMap.builder()
+ .put(attributeDef, "LU/AT/" + RandomStringUtils.randomNumeric(64))
+ .put(attributeDef2, RandomStringUtils.randomAlphabetic(10))
+ .put(attributeDef3, RandomStringUtils.randomAlphabetic(10)).put(attributeDef4, "2001-01-01").build();
+
+ val b = new AuthenticationResponse.Builder();
+ return b.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode("200")
+ .inResponseTo("_".concat(Random.nextHexRandom16()))
+ .subjectNameIdFormat("afaf")
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_PREFIX + RandomStringUtils.randomAlphabetic(5))
+ .attributes(attributeMap)
+ .build();
+ }
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java
new file mode 100644
index 00000000..5ebe8225
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java
@@ -0,0 +1,637 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+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.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateAuthnRequestTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+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.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
+public class GenerateAuthnRequestTaskTest {
+
+ @Autowired(required = true)
+ private GenerateAuthnRequestTask task;
+ @Autowired(required = true)
+ private DummySpecificCommunicationService commService;
+ @Autowired(required = true)
+ private MsConnectorDummyConfigMap basicConfig;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+ private DummySpConfiguration oaParam;
+ private Map<String, String> spConfig;
+
+
+ /**
+ * jUnit test set-up.
+ *
+ */
+ @Before
+ public void setUp() {
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+
+ pendingReq = new TestRequestImpl();
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.requesterId.useHashedForm", "true");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.entityId",
+ RandomStringUtils.randomAlphabetic(10));
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint",
+ "http://test/" + RandomStringUtils.randomAlphabetic(5));
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.requested.nameIdFormat");
+
+ }
+
+ @Test
+ public void missingIssuer() {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.entityId");
+
+ //execute test
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("Missing Issuer not detected");
+
+ } catch (final TaskExecutionException e) {
+ // forward URL is not set in example config
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e.getOriginalException(),
+ "Wrong exception");
+ Assert.assertEquals("wrong errorCode", "config.27", ((EaafException) e.getOriginalException())
+ .getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException())
+ .getParams().length);
+
+ }
+ }
+
+ @Test
+ public void missingForwardUrl() {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.forward.endpoint");
+
+ //execute test
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("Missing Forward-URL not detected");
+
+ } catch (final TaskExecutionException e) {
+ // forward URL is not set in example config
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e.getOriginalException(),
+ "Wrong exception");
+ Assert.assertEquals("wrong errorCode", "config.08", ((EaafException) e.getOriginalException())
+ .getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException())
+ .getParams().length);
+ Assert.assertEquals("wrong errorMsg", Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL, ((EaafException) e
+ .getOriginalException()).getParams()[0]);
+
+ }
+ }
+
+ @Test
+ public void selectUnknownStage() {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ String stage = RandomStringUtils.randomAlphabetic(5);
+ executionContext.put("selectedEnvironment", stage);
+
+ //execute test
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("Missing Forward-URL not detected");
+
+ } catch (final TaskExecutionException e) {
+ // forward URL is not set in example config
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e.getOriginalException(),
+ "Wrong exception");
+ Assert.assertEquals("wrong errorCode", "config.08", ((EaafException) e.getOriginalException())
+ .getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException())
+ .getParams().length);
+ Assert.assertEquals("wrong errorMsg", Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL + "." + stage, ((EaafException) e
+ .getOriginalException()).getParams()[0]);
+
+ }
+ }
+
+ @Test
+ public void selectQsEndpoint() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ executionContext.put("selectedEnvironment", "qs");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint.qs", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+ }
+
+ @Test
+ public void selectTestEndpoint() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ executionContext.put("selectedEnvironment", "test");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint.test", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+ }
+
+ @Test
+ public void selectDevEndpoint() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ executionContext.put("selectedEnvironment", "dev");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint.dev", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+ }
+
+ @Test
+ public void noCountryCode() {
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("No countryCode not detected");
+
+ } catch (final TaskExecutionException e) {
+ Assert.assertEquals("wrong pendingReqId", pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ org.springframework.util.Assert.isInstanceOf(EidasSAuthenticationException.class, e
+ .getOriginalException(), "Wrong exception");
+ Assert.assertEquals("wrong errorCode", "eidas.03", ((EaafException) e.getOriginalException())
+ .getErrorId());
+
+ }
+ }
+
+ @Test
+ public void withStaticProviderNameForPublicSPs() throws TaskExecutionException,
+ SpecificCommunicationException {
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.publicSectorTargets", ".*");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "true");
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs");
+
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertEquals("ProviderName is not Static",
+ Constants.DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP, eidasReq.getProviderName());
+ Assert.assertEquals("no PublicSP", "public", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", "http://eidas.europa.eu/LoA/high", eidasReq.getLevelOfAssurance());
+
+ }
+
+ @Test
+ public void withCustomStaticProviderNameForPublicSPs() throws TaskExecutionException,
+ SpecificCommunicationException {
+ String cc = RandomStringUtils.randomAlphabetic(2);
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, cc);
+
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.publicSectorTargets", ".*");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderNames", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs", "myNode");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertEquals("wrong issuer",
+ basicConfig.getBasicConfiguration("eidas.ms.auth.eIDAS.node_v2.entityId"), eidasReq.getIssuer());
+ Assert.assertEquals("ProviderName is not Static", "myNode", eidasReq.getProviderName());
+ Assert.assertEquals("no PublicSP", "public", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", "http://eidas.europa.eu/LoA/high", eidasReq.getLevelOfAssurance());
+ Assert.assertEquals("wrong CC", cc, eidasReq.getCitizenCountryCode());
+ assertNull("NameIdPolicy not null", eidasReq.getNameIdFormat());
+
+ }
+
+ @Test
+ public void withDynamicProviderNameForPublicSPs() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException, UnsupportedEncodingException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ executionContext.put("selectedEnvironment", "prod");
+
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "false");
+
+ String nameIdFormat = RandomStringUtils.randomAlphabetic(10);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.requested.nameIdFormat", nameIdFormat);
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertNotNull("ProviderName found", eidasReq.getProviderName());
+ Assert.assertEquals("PrividerName", providerName, eidasReq.getProviderName());
+ Assert.assertNull("RequesterId found", eidasReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", EaafConstants.EIDAS_LOA_HIGH,
+ eidasReq.getLevelOfAssurance());
+
+ Assert.assertEquals("Wrong req. attr. size", 4, eidasReq.getRequestedAttributes().size());
+ Assert.assertEquals("NameIdFormat", nameIdFormat, eidasReq.getNameIdFormat());
+
+ }
+
+ @Test
+ public void publicSpWithCountryLu() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException, UnsupportedEncodingException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "LU");
+ executionContext.put("selectedEnvironment", "prod");
+
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertEquals("PrividerName", "myNode", eidasReq.getProviderName());
+ Assert.assertEquals("RequesterId found", "myNode", eidasReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", EaafConstants.EIDAS_LOA_HIGH,
+ eidasReq.getLevelOfAssurance());
+
+ Assert.assertEquals("Wrong req. attr. size", 4, eidasReq.getRequestedAttributes().size());
+
+ }
+
+ @Test
+ public void privateSpWithCountryLu() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException, UnsupportedEncodingException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "LU");
+ executionContext.put("selectedEnvironment", "prod");
+
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ String requesterId = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+ pendingReq.setRawDataToTransaction(Constants.DATA_REQUESTERID, requesterId);
+
+ spConfig.put("target",
+ EaafConstants.URN_PREFIX_WBPK_TARGET_WITH_X + "FN+" + RandomStringUtils.randomNumeric(6));
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "true");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertEquals("PrividerName", "myNode", eidasReq.getProviderName());
+ Assert.assertEquals("RequesterId", "myNode", eidasReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "private", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", EaafConstants.EIDAS_LOA_HIGH,
+ eidasReq.getLevelOfAssurance());
+
+ Assert.assertEquals("Wrong req. attr. size", 4, eidasReq.getRequestedAttributes().size());
+
+ }
+
+ @Test
+ public void withEidasNodePostReqNotValidTemplate() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException, UnsupportedEncodingException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "false");
+
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "POST");
+
+ //execute test
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("Missing template not detected");
+
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("ErrorCode", "Could not resolve view with name 'eidas_node_forward.html' ",
+ ((GuiBuildException) e.getOriginalException()).getMessage());
+
+ }
+ }
+
+ @Test
+ public void withDynamicProviderNameForPrivateSPs() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ spConfig.put("target",
+ EaafConstants.URN_PREFIX_WBPK_TARGET_WITH_X + "FN+" + RandomStringUtils.randomNumeric(6));
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+ pendingReq.setRawDataToTransaction(Constants.DATA_REQUESTERID, "http://junit.sp");
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "false");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertEquals("PrividerName", providerName, eidasReq.getProviderName());
+ Assert.assertEquals("RequesterId", "Wr8LrrVf5SYneblOlZdZNaLQQCCgzklfKQvyeZjBx10=", eidasReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "private", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", "http://eidas.europa.eu/LoA/high", eidasReq.getLevelOfAssurance());
+
+ }
+
+ @Test
+ public void privateSPWithoutRequestIdHashing() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ spConfig.put("target",
+ EaafConstants.URN_PREFIX_WBPK_TARGET_WITH_X + "FN+" + RandomStringUtils.randomNumeric(6));
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ String requesterId = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+ pendingReq.setRawDataToTransaction(Constants.DATA_REQUESTERID, requesterId);
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "true");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.requesterId.useHashedForm", "false");
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+
+ //perform test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+ Assert.assertNotNull("No redirect header", httpResp.getHeaderValue("Location"));
+ Assert.assertTrue("Wrong redirect endpoint",
+ ((String) httpResp.getHeaderValue("Location")).startsWith(dynEndPoint));
+
+
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertEquals("PrividerName", providerName, eidasReq.getProviderName());
+ Assert.assertEquals("RequesterId", requesterId, eidasReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "private", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", "http://eidas.europa.eu/LoA/high", eidasReq.getLevelOfAssurance());
+
+ }
+
+ @Test
+ public void withoutProviderNameForPublicSPs() throws TaskExecutionException,
+ SpecificCommunicationException, EaafStorageException {
+ //set-up test
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "CC");
+ String providerName = RandomStringUtils.randomAlphanumeric(10);
+ pendingReq.setRawDataToTransaction(Constants.DATA_PROVIDERNAME, providerName);
+
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.publicSectorTargets");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName", "false");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier", "false");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "false");
+
+
+ String dynEndPoint = "http://test/" + RandomStringUtils.randomAlphabetic(5);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.endpoint", dynEndPoint);
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.forward.method", "GET");
+
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ Assert.assertEquals("Wrong http statusCode", 302, httpResp.getStatus());
+
+ final ILightRequest eidasReq = commService.getAndRemoveRequest(null, null);
+
+ Assert.assertNull("ProviderName found", eidasReq.getProviderName());
+ Assert.assertNull("RequesterId found", eidasReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", eidasReq.getSpType());
+ Assert.assertEquals("wrong LoA", "http://eidas.europa.eu/LoA/high", eidasReq.getLevelOfAssurance());
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveEidasResponseTaskTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveEidasResponseTaskTest.java
new file mode 100644
index 00000000..53a49bac
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveEidasResponseTaskTest.java
@@ -0,0 +1,223 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummySpConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAuthnResponseTask;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+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.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import lombok.val;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+public class ReceiveEidasResponseTaskTest {
+
+ @Autowired(required = true)
+ private ReceiveAuthnResponseTask task;
+
+ @Autowired(required = true)
+ private MsConnectorDummyConfigMap basicConfig;
+ @Autowired
+ protected EidasAttributeRegistry attrRegistry;
+
+ @Autowired private IRequestStorage storage;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+ private MsConnectorDummySpConfiguration oaParam;
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false");
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.eid.testidentity.default", "false");
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new MsConnectorDummySpConfiguration(spConfig, basicConfig);
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+ pendingReq = new TestRequestImpl();
+
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+ pendingReq.setTransactionId("avaasbav");
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "LU");
+ executionContext.put(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT, true);
+
+ }
+
+ @Test
+ public void missingEidasResponse() {
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("No eIDAS response not detected");
+
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("ErrorId", "eidas.01",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+ }
+
+ @Test
+ public void notSuccessEidasResponse() throws URISyntaxException {
+ String statusCode = RandomStringUtils.randomAlphabetic(10);
+ httpReq.setAttribute(Constants.DATA_FULL_EIDAS_RESPONSE,
+ buildDummyAuthResponse(statusCode));
+
+
+ try {
+ task.execute(pendingReq, executionContext);
+ Assert.fail("No eIDAS response not detected");
+
+ } catch (TaskExecutionException e) {
+ Assert.assertEquals("ErrorId", "eidas.02",
+ ((EaafException) e.getOriginalException()).getErrorId());
+ Assert.assertEquals("wrong parameter size", 2, ((EaafException) e.getOriginalException())
+ .getParams().length);
+ Assert.assertEquals("wrong errorMsg", statusCode, ((EaafException) e
+ .getOriginalException()).getParams()[0]);
+
+ }
+ }
+
+ @Test
+ public void success() throws URISyntaxException, TaskExecutionException, PendingReqIdValidationException {
+ @NotNull
+ AuthenticationResponse eidasResponse = buildDummyAuthResponse(Constants.SUCCESS_URI);
+ httpReq.setAttribute(Constants.DATA_FULL_EIDAS_RESPONSE, eidasResponse);
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "LU");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+
+ final EidAuthProcessDataWrapper authProcessData = storedReq.getSessionData(EidAuthProcessDataWrapper.class);
+ Assert.assertEquals("LoA", eidasResponse.getLevelOfAssurance(), authProcessData.getQaaLevel());
+ Assert.assertNotNull("eIDAS response",
+ authProcessData.getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertEquals("eIDAS response", eidasResponse,
+ authProcessData.getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertFalse("testIdentity flag", authProcessData.isTestIdentity());
+
+ }
+
+ @Test
+ public void successWithTestIdentity() throws URISyntaxException, TaskExecutionException, PendingReqIdValidationException {
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.eid.testidentity.default", "true");
+
+ @NotNull
+ AuthenticationResponse eidasResponse = buildDummyAuthResponse(Constants.SUCCESS_URI);
+ httpReq.setAttribute(Constants.DATA_FULL_EIDAS_RESPONSE, eidasResponse);
+ executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "LU");
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+
+ final EidAuthProcessDataWrapper authProcessData = storedReq.getSessionData(EidAuthProcessDataWrapper.class);
+ Assert.assertEquals("LoA", eidasResponse.getLevelOfAssurance(), authProcessData.getQaaLevel());
+ Assert.assertNotNull("eIDAS response",
+ authProcessData.getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertEquals("eIDAS response", eidasResponse,
+ authProcessData.getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE));
+ Assert.assertTrue("testIdentity flag", authProcessData.isTestIdentity());
+
+ }
+
+
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponse(String statusCode) throws URISyntaxException {
+ final AttributeDefinition attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+
+ final ImmutableAttributeMap attributeMap = ImmutableAttributeMap.builder()
+ .put(attributeDef, "LU/AT/" + RandomStringUtils.randomNumeric(64))
+ .put(attributeDef2, RandomStringUtils.randomAlphabetic(10))
+ .put(attributeDef3, RandomStringUtils.randomAlphabetic(10)).put(attributeDef4, "2001-01-01").build();
+
+ val b = new AuthenticationResponse.Builder();
+ return b.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(statusCode)
+ .inResponseTo("_".concat(Random.nextHexRandom16()))
+ .subjectNameIdFormat("afaf")
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .attributes(attributeMap)
+ .build();
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/JoseUtilsTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/JoseUtilsTest.java
new file mode 100644
index 00000000..ad38e371
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/JoseUtilsTest.java
@@ -0,0 +1,139 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.utils;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Provider;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.jose4j.jwa.AlgorithmConstraints;
+import org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
+import org.jose4j.jws.AlgorithmIdentifiers;
+import org.jose4j.lang.JoseException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils.JwsResult;
+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.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;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+public class JoseUtilsTest {
+
+ @Autowired private EaafKeyStoreFactory keyStoreFactory;
+
+ private static final List<String> AUTH_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList(
+ Arrays.asList(
+ AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256,
+ AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512,
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA256,
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA512));
+
+
+ @Test
+ public void missingKey() throws EaafException, JoseException, KeyStoreException, IOException {
+
+ KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName("jUnittest");
+ config.setKeyStoreType(KeyStoreType.JKS);
+ config.setSoftKeyStoreFilePath("../data/junit.jks");
+ config.setSoftKeyStorePassword("password");
+
+ Pair<KeyStore, Provider> keyStore = keyStoreFactory.buildNewKeyStore(config);
+ String payLoad = RandomStringUtils.randomAlphanumeric(100);
+
+ //check signing
+ try {
+ JoseUtils.createSignature(keyStore, "notExist", "password".toCharArray(), payLoad , true, "jUnitTest");
+ Assert.fail("missing Key not detected");
+
+ } catch (EaafException e) {
+ Assert.assertEquals("ErrorId", "internal.keystore.09", e.getErrorId());
+
+ }
+ }
+
+ @Test
+ public void createRsaSignature() throws EaafException, JoseException, KeyStoreException, IOException {
+
+ KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName("jUnittest");
+ config.setKeyStoreType(KeyStoreType.JKS);
+ config.setSoftKeyStoreFilePath("../data/junit.jks");
+ config.setSoftKeyStorePassword("password");
+
+ Pair<KeyStore, Provider> keyStore = keyStoreFactory.buildNewKeyStore(config);
+ String payLoad = RandomStringUtils.randomAlphanumeric(100);
+
+ //check signing
+ String result = JoseUtils.createSignature(keyStore, "meta", "password".toCharArray(), payLoad , true, "jUnitTest");
+
+ Assert.assertNotNull("signed message", result);
+ Assert.assertFalse("signed msg empty", result.isEmpty());
+
+
+ //validate
+ List<X509Certificate> trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(keyStore.getFirst());
+ final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT,
+ AUTH_ALGORITHM_WHITELIST_SIGNING
+ .toArray(new String[AUTH_ALGORITHM_WHITELIST_SIGNING.size()]));
+ JwsResult verify = JoseUtils.validateSignature(result, trustedCerts, constraints);
+
+ Assert.assertTrue("sig. verify", verify.isValid());
+ Assert.assertEquals("payload", payLoad, verify.getPayLoad());
+
+ }
+
+ @Test
+ public void createEccSignature() throws EaafException, JoseException, KeyStoreException, IOException {
+
+ KeyStoreConfiguration config = new KeyStoreConfiguration();
+ config.setFriendlyName("jUnittest");
+ config.setKeyStoreType(KeyStoreType.JKS);
+ config.setSoftKeyStoreFilePath("../data/junit.jks");
+ config.setSoftKeyStorePassword("password");
+
+ Pair<KeyStore, Provider> keyStore = keyStoreFactory.buildNewKeyStore(config);
+ String payLoad = RandomStringUtils.randomAlphanumeric(100);
+
+ //check signing
+ String result = JoseUtils.createSignature(keyStore, "sig", "password".toCharArray(), payLoad , true, "jUnitTest");
+
+ Assert.assertNotNull("signed message", result);
+ Assert.assertFalse("signed msg empty", result.isEmpty());
+
+
+ //validate
+ List<X509Certificate> trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(keyStore.getFirst());
+ final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT,
+ AUTH_ALGORITHM_WHITELIST_SIGNING
+ .toArray(new String[AUTH_ALGORITHM_WHITELIST_SIGNING.size()]));
+ JwsResult verify = JoseUtils.validateSignature(result, trustedCerts, constraints);
+
+ Assert.assertTrue("sig. verify", verify.isValid());
+ Assert.assertEquals("payload", payLoad, verify.getPayLoad());
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasAttributePostProcessingTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasAttributePostProcessingTest.java
new file mode 100644
index 00000000..9bb51cd9
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasAttributePostProcessingTest.java
@@ -0,0 +1,460 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.test.validation;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.joda.time.DateTime;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.CcSpecificEidProcessingService;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public class EidasAttributePostProcessingTest {
+
+ @Autowired
+ private CcSpecificEidProcessingService postProcessor;
+
+ // lower case
+ private static final String P1_eIDASID =
+ "DE/AT/532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25";
+ private static final String P1_GIVENNAME = "Max";
+ private static final String P1_FAMILYNAME = "Mustermann";
+ private static final DateTime P1_DATEOFBIRTH = DateTime.now();
+ private static final String P1_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P1_BIRTHNAME = "Musterkind";
+
+ // mixed
+ private static final String P3_eIDASID =
+ "DE/AT/532eaabd9574880dbf76b9b8cc00832c20A6ec113d682299550d7a6e0f345e25";
+ private static final String P3_GIVENNAME = "Max";
+ private static final String P3_FAMILYNAME = "Mustermann";
+ private static final DateTime P3_DATEOFBIRTH = DateTime.now();
+ private static final String P3_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P3_BIRTHNAME = "Musterkind";
+
+ // upper case
+ private static final String P4_eIDASID =
+ "DE/AT/532EAABD9574880DBF76B9B8CC00832C20A6EC113D682299550D7A6E0F345E25";
+ private static final String P4_GIVENNAME = "Max";
+ private static final String P4_FAMILYNAME = "Mustermann";
+ private static final DateTime P4_DATEOFBIRTH = DateTime.now();
+ private static final String P4_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P4_BIRTHNAME = "Musterkind";
+
+ // To long identifier
+ private static final String P5_eIDASID =
+ "DE/AT/532EAABD9574880DBF76B9B8CC00832C20A6EC113D682299550D7A6E0F345E251";
+ private static final String P5_GIVENNAME = "Max";
+ private static final String P5_FAMILYNAME = "Mustermann";
+ private static final DateTime P5_DATEOFBIRTH = DateTime.now();
+ private static final String P5_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P5_BIRTHNAME = "Musterkind";
+
+ // to short identifier
+ private static final String P6_eIDASID = "DE/AT/532EAABD9574880DBF76B9B8CC00832C20A6EC113D682299550D7A6E0F";
+ private static final String P6_GIVENNAME = "Max";
+ private static final String P6_FAMILYNAME = "Mustermann";
+ private static final DateTime P6_DATEOFBIRTH = DateTime.now();
+ private static final String P6_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P6_BIRTHNAME = "Musterkind";
+
+ // no hex encoded identifier
+ private static final String P7_eIDASID = "DE/AT/532EAABD9574880DBF76B9B8CC00832C20A6EC113D682299550D7A6E0F";
+ private static final String P7_GIVENNAME = "Max";
+ private static final String P7_FAMILYNAME = "Mustermann";
+ private static final DateTime P7_DATEOFBIRTH = DateTime.now();
+ private static final String P7_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P7_BIRTHNAME = "Musterkind";
+
+ private static final String P2_eIDASID =
+ "EE/AT/asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd";
+ private static final String P2_GIVENNAME = "Max";
+ private static final String P2_FAMILYNAME = "Mustermann";
+ private static final DateTime P2_DATEOFBIRTH = DateTime.now();
+ private static final String P2_PLACEOFBIRTH = "Nirgendwo";
+ private static final String P2_BIRTHNAME = "Musterkind";
+
+ /**
+ * jUnit class initializer.
+ *
+ * @throws IOException In case of an error
+ */
+ @BeforeClass
+ public static void classInitializer() throws IOException {
+ final String current = new java.io.File(".").toURI().toString();
+ System.setProperty("eidas.ms.configuration", current + "../../basicConfig/default_config.properties");
+
+ }
+
+ @Test
+ public void deWithHexLowerCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P1_eIDASID,
+ P1_FAMILYNAME,
+ P1_GIVENNAME,
+ P1_DATEOFBIRTH,
+ P1_PLACEOFBIRTH,
+ P1_BIRTHNAME));
+
+ validate(result,
+ "Uy6qvZV0iA2/drm4zACDLCCm7BE9aCKZVQ16bg80XiU=",
+ P1_FAMILYNAME,
+ P1_GIVENNAME,
+ P1_DATEOFBIRTH,
+ P1_PLACEOFBIRTH,
+ P1_BIRTHNAME);
+
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+
+ }
+ }
+
+ @Test
+ public void deWithHexMixedCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P3_eIDASID,
+ P3_FAMILYNAME,
+ P3_GIVENNAME,
+ P3_DATEOFBIRTH,
+ P3_PLACEOFBIRTH,
+ P3_BIRTHNAME));
+
+ validate(result,
+ "Uy6qvZV0iA2/drm4zACDLCCm7BE9aCKZVQ16bg80XiU=",
+ P3_FAMILYNAME,
+ P3_GIVENNAME,
+ P3_DATEOFBIRTH,
+ P3_PLACEOFBIRTH,
+ P3_BIRTHNAME);
+
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+
+ }
+ }
+
+ @Test
+ public void deWithHexUpperCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P4_eIDASID,
+ P4_FAMILYNAME,
+ P4_GIVENNAME,
+ P4_DATEOFBIRTH,
+ P4_PLACEOFBIRTH,
+ P4_BIRTHNAME));
+
+ validate(result,
+ "Uy6qvZV0iA2/drm4zACDLCCm7BE9aCKZVQ16bg80XiU=",
+ P4_FAMILYNAME,
+ P4_GIVENNAME,
+ P4_DATEOFBIRTH,
+ P4_PLACEOFBIRTH,
+ P4_BIRTHNAME);
+
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+
+ }
+ }
+
+ @Test
+ public void deWithHexTooLongCase() throws Exception {
+ try {
+ postProcessor.postProcess(
+ generateInputData(
+ P5_eIDASID,
+ P5_FAMILYNAME,
+ P5_GIVENNAME,
+ P5_DATEOFBIRTH,
+ P5_PLACEOFBIRTH,
+ P5_BIRTHNAME));
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("Too long input accepted");
+ }
+
+ @Test
+ public void deWithHexTooShortCase() throws Exception {
+ try {
+ postProcessor.postProcess(
+ generateInputData(
+ P6_eIDASID,
+ P6_FAMILYNAME,
+ P6_GIVENNAME,
+ P6_DATEOFBIRTH,
+ P6_PLACEOFBIRTH,
+ P6_BIRTHNAME));
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("Too short input accepted");
+ }
+
+ @Test
+ public void deWithNoHexCase() throws Exception {
+ try {
+ postProcessor.postProcess(
+ generateInputData(
+ P7_eIDASID,
+ P7_FAMILYNAME,
+ P7_GIVENNAME,
+ P7_DATEOFBIRTH,
+ P7_PLACEOFBIRTH,
+ P7_BIRTHNAME));
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("Not hex encoded input accepted");
+ }
+
+ @Test
+ public void eeTestCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P2_eIDASID,
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME));
+
+ validate(result,
+ "asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd",
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME);
+
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+
+ }
+ }
+
+ @Test
+ public void eeTestFamilyNameMissingCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P2_eIDASID,
+ null,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME));
+
+ validate(result,
+ "asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd",
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME);
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("FamilyName missing input accepted");
+
+ }
+
+ @Test
+ public void eeTestGivenNameMissingCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P2_eIDASID,
+ P2_FAMILYNAME,
+ null,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME));
+
+ validate(result,
+ "asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd",
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME);
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("GivenName missing input accepted");
+
+ }
+
+ @Test
+ public void eeTestDateOfBirthMissingCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ P2_eIDASID,
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ null,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME));
+
+ validate(result,
+ "asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd",
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME);
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("DateOfBirth missing input accepted");
+
+ }
+
+ @Test
+ public void eeTestIdMissingCase() throws Exception {
+ try {
+ final ErnbEidData result = postProcessor.postProcess(
+ generateInputData(
+ null,
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME));
+
+ validate(result,
+ "asfasfasdfasdfasdfasdfasdfasvafasdfasdfasdfasdfasdfasvascasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd",
+ P2_FAMILYNAME,
+ P2_GIVENNAME,
+ P2_DATEOFBIRTH,
+ P2_PLACEOFBIRTH,
+ P2_BIRTHNAME);
+
+ } catch (final Exception e) {
+ return;
+
+ }
+
+ fail("eIDAS-Id missing input accepted");
+
+ }
+
+ private Map<String, Object> generateInputData(String id, String familyName, String givenName,
+ DateTime dateOfBirth, String placeOfBirth, String birthName) {
+ final Map<String, Object> result = new HashMap<>();
+ result.put(Constants.eIDAS_ATTR_PERSONALIDENTIFIER, id);
+ result.put(Constants.eIDAS_ATTR_CURRENTGIVENNAME, givenName);
+ result.put(Constants.eIDAS_ATTR_CURRENTFAMILYNAME, familyName);
+ result.put(Constants.eIDAS_ATTR_DATEOFBIRTH, dateOfBirth);
+ result.put(Constants.eIDAS_ATTR_PLACEOFBIRTH, placeOfBirth);
+ result.put(Constants.eIDAS_ATTR_BIRTHNAME, birthName);
+ return result;
+
+ }
+
+ private void validate(ErnbEidData result, String id, String familyName, String givenName,
+ DateTime dateOfBirth, String placeOfBirth, String birthName) {
+ if (!result.getPseudonym().equals(id)) {
+ fail(result.getPseudonym() + "is not equal to " + id);
+ }
+
+ if (!result.getFamilyName().equals(familyName)) {
+ fail(result.getFamilyName() + "is not equal to " + familyName);
+ }
+
+ if (!result.getGivenName().equals(givenName)) {
+ fail(result.getGivenName() + "is not equal to " + givenName);
+ }
+
+ if (!result.getDateOfBirth().equals(dateOfBirth)) {
+ fail(result.getDateOfBirth() + "is not equal to " + dateOfBirth);
+ }
+
+ if (!result.getFormatedDateOfBirth().equals(new SimpleDateFormat("yyyy-MM-dd").format(dateOfBirth
+ .toDate()))) {
+ fail(result.getDateOfBirth() + "is not equal to " + new SimpleDateFormat("yyyy-MM-dd").format(
+ dateOfBirth.toDate()));
+ }
+
+ if (!result.getPlaceOfBirth().equals(placeOfBirth)) {
+ fail(result.getPlaceOfBirth() + "is not equal to " + placeOfBirth);
+ }
+
+ if (!result.getBirthName().equals(birthName)) {
+ fail(result.getBirthName() + "is not equal to " + birthName);
+ }
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java
new file mode 100644
index 00000000..610801a6
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.test.validation;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+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.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.CcSpecificEidProcessingService;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_realConfig.xml"})
+@TestPropertySource(locations = {"classpath:/config/junit_config_de_attributes.properties"})
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public class EidasRequestPreProcessingFirstTest {
+
+ @Autowired
+ private IConfigurationWithSP basicConfig;
+ @Autowired
+ private CcSpecificEidProcessingService preProcessor;
+
+ private TestRequestImpl pendingReq;
+ private DummySpConfiguration oaParam;
+ private Builder authnRequestBuilder;
+ private Map<String, String> spConfig;
+
+ /**
+ * jUnit class initializer.
+ *
+ * @throws IOException In case of an error
+ */
+ @BeforeClass
+ public static void classInitializer() throws IOException {
+// final String current = new java.io.File(".").toURI().toString();
+// System.setProperty("eidas.ms.configuration",
+// current + "src/test/resources/config/junit_config_de_attributes.properties");
+
+ }
+
+ /**
+ * jUnit test set-up.
+ *
+ */
+ @Before
+ public void setUp() {
+
+ spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+
+ pendingReq = new TestRequestImpl();
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+
+ authnRequestBuilder = LightRequest.builder();
+ authnRequestBuilder.id(UUID.randomUUID().toString());
+ authnRequestBuilder.issuer("Test");
+ authnRequestBuilder.levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH);
+
+ }
+
+ @Test
+ public void prePreProcessGeneric() throws EidPostProcessingException {
+ final String testCountry = "XX";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertEquals("ProviderName is not Static",
+ Constants.DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP, lightReq.getProviderName());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 4, lightReq.getRequestedAttributes().size());
+
+ }
+
+ @Test
+ public void prePreProcessGenericNoCountryCode() throws EidPostProcessingException {
+ final String testCountry = "XX";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(null, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertEquals("ProviderName is not Static",
+ Constants.DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP, lightReq.getProviderName());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 4, lightReq.getRequestedAttributes().size());
+
+ }
+
+ @Test
+ public void prePreProcessDE() throws EidPostProcessingException {
+
+ final String testCountry = "DE";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertEquals("ProviderName is not Static",
+ Constants.DEFAULT_PROPS_EIDAS_NODE_STATIC_PROVIDERNAME_FOR_PUBLIC_SP, lightReq.getProviderName());
+ Assert.assertNotSame("RequesterId was set", lightReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 8, lightReq.getRequestedAttributes().size());
+
+ }
+
+ @Test
+ public void prePreProcessNlWithUpgrade() throws EidPostProcessingException {
+
+ final String testCountry = "NL";
+ spConfig.put("loa", EaafConstants.EIDAS_LOA_LOW);
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ authnRequestBuilder.levelOfAssurance(EaafConstants.EIDAS_LOA_LOW);
+
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertNotSame("RequesterId was set", lightReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 4, lightReq.getRequestedAttributes().size());
+
+ Assert.assertEquals("wrong LoA", EaafConstants.EIDAS_LOA_SUBSTANTIAL, lightReq.getLevelOfAssurance());
+
+ }
+
+ @Test
+ public void prePreProcessNlWithOutUpgrade() throws EidPostProcessingException {
+
+ final String testCountry = "NL";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertNotSame("RequesterId was set", lightReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 4, lightReq.getRequestedAttributes().size());
+
+ Assert.assertEquals("wrong LoA", EaafConstants.EIDAS_LOA_HIGH, lightReq.getLevelOfAssurance());
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingSecondTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingSecondTest.java
new file mode 100644
index 00000000..9ee38296
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingSecondTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.eidas.v2.test.validation;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.CcSpecificEidProcessingService;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
+public class EidasRequestPreProcessingSecondTest {
+
+ @Autowired
+ private MsConnectorDummyConfigMap basicConfig;
+ @Autowired
+ private CcSpecificEidProcessingService preProcessor;
+
+ private TestRequestImpl pendingReq;
+ private DummySpConfiguration oaParam;
+ private Builder authnRequestBuilder;
+
+
+ /**
+ * jUnit test set-up.
+ *
+ */
+ @Before
+ public void setUp() {
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+
+ pendingReq = new TestRequestImpl();
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+
+ authnRequestBuilder = LightRequest.builder();
+ authnRequestBuilder.id(UUID.randomUUID().toString());
+ authnRequestBuilder.issuer("Test");
+ authnRequestBuilder.levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH);
+
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.requesterId.lu.useStaticRequesterForAll", "true");
+
+ }
+
+ @Test
+ public void prePreProcessDeUnknownAttribute() throws EidPostProcessingException {
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs", "myNode");
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs", "true");
+
+ final String testCountry = "DE";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertEquals("ProviderName is not Static", "myNode", lightReq.getProviderName());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 8, lightReq.getRequestedAttributes().size());
+
+ }
+
+
+ /*
+ * Set ProviderName according to general configuration
+ */
+ @Test
+ public void prePreProcessLuPublicSpWithoutRequestId() throws EidPostProcessingException {
+
+ basicConfig.putConfigValue(
+ "eidas.ms.auth.eIDAS.node_v2.requesterId.lu.useStaticRequesterForAll", "false");
+
+ final String testCountry = "LU";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertEquals("ProviderName is not Static", "myNode", lightReq.getProviderName());
+ Assert.assertNull("RequesterId", lightReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 4, lightReq.getRequestedAttributes().size());
+
+ }
+
+ /*
+ * Always set requesterId and providername in case of country LU
+ */
+ @Test
+ public void prePreProcessLuPublicSpWithStaticRequesterId() throws EidPostProcessingException {
+
+
+ final String testCountry = "LU";
+ authnRequestBuilder.citizenCountryCode(testCountry);
+ preProcessor.preProcess(testCountry, pendingReq, authnRequestBuilder);
+
+ final LightRequest lightReq = authnRequestBuilder.build();
+
+ Assert.assertEquals("ProviderName is not Static",
+ "myNode", lightReq.getProviderName());
+ Assert.assertEquals("RequesterId is not Static",
+ "myNode", lightReq.getRequesterId());
+ Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
+ Assert.assertEquals("Requested attribute size not match", 4, lightReq.getRequestedAttributes().size());
+
+ }
+
+}
diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasResponseValidatorTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasResponseValidatorTest.java
new file mode 100644
index 00000000..b1f1b164
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasResponseValidatorTest.java
@@ -0,0 +1,333 @@
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.validation;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.google.common.collect.ImmutableSet;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummySpConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasValidationException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.validator.EidasResponseValidator;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap.Builder;
+import eu.eidas.auth.commons.attribute.impl.StringAttributeValue;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import lombok.val;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_tasks_test.xml",
+ "/SpringTest-context_basic_mapConfig.xml"})
+public class EidasResponseValidatorTest {
+
+ @Autowired private MsConnectorDummyConfigMap basicConfig;
+ @Autowired protected EidasAttributeRegistry attrRegistry;
+
+ private TestRequestImpl pendingReq;
+ private MsConnectorDummySpConfiguration oaParam;
+
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new MsConnectorDummySpConfiguration(spConfig, basicConfig);
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+ pendingReq = new TestRequestImpl();
+
+ pendingReq.setSpConfig(oaParam);
+ pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue());
+ pendingReq.setAuthUrl("http://test.com/");
+ pendingReq.setTransactionId("avaasbav");
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+
+ }
+
+
+ @Test
+ public void loaFromResponseToLow() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ "LU/AT/" + RandomStringUtils.randomNumeric(10),
+ EaafConstants.EIDAS_LOA_LOW,
+ false);
+ String spCountry = "AT";
+ String citizenCountryCode = "XX";
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.06", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "http://eidas.europa.eu/LoA/low",
+ e.getParams()[0]);
+
+ }
+ }
+
+ @Test
+ public void noEidasSpCountry() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ "LU/AT/" + RandomStringUtils.randomNumeric(10),
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ false);
+ String spCountry = null;
+ String citizenCountryCode = "LU";
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.07", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 2, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "PersonIdentifier",
+ e.getParams()[0]);
+ Assert.assertEquals("wrong errorMsg",
+ "Destination country does not match to SP country",
+ e.getParams()[1]);
+
+ }
+ }
+
+ @Test
+ public void noEidasResponseCountry() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ "LU/AT/" + RandomStringUtils.randomNumeric(10),
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ false);
+ String spCountry = "AT";
+ String citizenCountryCode = null;
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.07", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 2, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "PersonIdentifier",
+ e.getParams()[0]);
+ Assert.assertEquals("wrong errorMsg",
+ "Citizen country does not match to eIDAS-node country that generates the response",
+ e.getParams()[1]);
+
+ }
+ }
+
+ @Test
+ public void wrongEidasResponseCountry() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ "LU/AT/" + RandomStringUtils.randomNumeric(10),
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ false);
+ String spCountry = "AT";
+ String citizenCountryCode = "XX";
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.07", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 2, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "PersonIdentifier",
+ e.getParams()[0]);
+ Assert.assertEquals("wrong errorMsg",
+ "Citizen country does not match to eIDAS-node country that generates the response",
+ e.getParams()[1]);
+
+ }
+ }
+
+ @Test
+ public void missingPersonalIdentifier() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ null,
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ false);
+ String spCountry = "AT";
+ String citizenCountryCode = "LU";
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.05", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "NO 'PersonalIdentifier' attriubte",
+ e.getParams()[0]);
+
+ }
+ }
+
+ @Test
+ public void moreThanOnePersonalIdentifier() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ null,
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ true);
+ String spCountry = "AT";
+ String citizenCountryCode = "LU";
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.05", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 1, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "NO 'PersonalIdentifier' attriubte",
+ e.getParams()[0]);
+
+ }
+ }
+
+ @Test
+ public void emptyPersonalIdentifier() throws URISyntaxException {
+ //set-up
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ "",
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ false);
+ String spCountry = "AT";
+ String citizenCountryCode = "LU";
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+ try {
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, citizenCountryCode, attrRegistry);
+ Assert.fail("Wrong eIDAS response not detected");
+
+ } catch (EidasValidationException e) {
+ Assert.assertEquals("ErrorId", "eidas.07", e.getErrorId());
+ Assert.assertEquals("wrong parameter size", 2, e.getParams().length);
+ Assert.assertEquals("wrong errorMsg", "PersonIdentifier",
+ e.getParams()[0]);
+ Assert.assertEquals("wrong errorMsg",
+ "Wrong identifier format",
+ e.getParams()[1]);
+
+ }
+ }
+
+ @Test
+ public void validResponse() throws URISyntaxException, EidasValidationException {
+ //set-up
+
+ String spCountry = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ String cCountry = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+
+ ILightResponse eidasResponse = buildDummyAuthResponse(
+ cCountry + "/" + spCountry + "/" + RandomStringUtils.randomAlphanumeric(20),
+ EaafConstants.EIDAS_LOA_SUBSTANTIAL,
+ false);
+
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH, EaafConstants.EIDAS_LOA_SUBSTANTIAL));
+
+
+ //execute test
+
+ EidasResponseValidator.validateResponse(pendingReq, eidasResponse, spCountry, cCountry, attrRegistry);
+
+ }
+
+
+ private AuthenticationResponse buildDummyAuthResponse(String personalId, String loa, boolean moreThanOnePersonalId)
+ throws URISyntaxException {
+
+
+ final AttributeDefinition personIdattributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+
+ final Builder attributeMap = ImmutableAttributeMap.builder();
+ if (personalId != null) {
+ if (moreThanOnePersonalId) {
+ ImmutableSet values = ImmutableSet.of(new StringAttributeValue(personalId),
+ new StringAttributeValue("XX/YY/" + RandomStringUtils.randomAlphanumeric(10)));
+ attributeMap.put(personIdattributeDef, values);
+
+ } else {
+ attributeMap.put(personIdattributeDef, personalId);
+
+ }
+ }
+
+ val b = new AuthenticationResponse.Builder();
+ return b.id("_".concat(Random.nextHexRandom16()))
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .subject(RandomStringUtils.randomAlphabetic(10))
+ .statusCode(Constants.SUCCESS_URI)
+ .inResponseTo("_".concat(Random.nextHexRandom16()))
+ .subjectNameIdFormat("afaf")
+ .levelOfAssurance(loa)
+ .attributes(attributeMap.build())
+ .build();
+ }
+}
+
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_mapConfig.xml b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_mapConfig.xml
new file mode 100644
index 00000000..fe9ff441
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_mapConfig.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">
+
+ <context:annotation-config />
+
+ <bean id="dummyMapBasedConfiguration"
+ class="at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap">
+ <constructor-arg value="/config/junit_config_1.properties" />
+ <property name="configRootDirSufix" value="src/test/resources/config" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_realConfig.xml b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_realConfig.xml
new file mode 100644
index 00000000..79695f69
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_realConfig.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">
+
+ <context:annotation-config />
+
+ <!--
+ <bean id="BasicMSSpecificNodeConfig"
+ class="at.asitplus.eidas.specific.connector.config.BasicConfigurationProvider">
+ <constructor-arg
+ value="#{systemProperties['eidas.ms.configuration']}" />
+ </bean>
+ -->
+
+ <bean id="springBootBasicConfingProvider"
+ class="at.asitplus.eidas.specific.core.config.SpringBootBasicConfigurationProvider" />
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_test.xml b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_test.xml
new file mode 100644
index 00000000..f31e5063
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_basic_test.xml
@@ -0,0 +1,73 @@
+<?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="SZRClientForeIDAS"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient" />
+
+ <!-- <bean id="eIDASDataStore" class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.eIDASDataStore"
+ /> -->
+
+ <bean id="springManagedSpecificConnectorCommunicationService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService" />
+
+ <bean id="specificConnectorAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/eidas-attributes.xml" />
+ </bean>
+
+ <bean id="specificConnectorAdditionalAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/additional-attributes.xml" />
+ </bean>
+
+ <bean id="attributeRegistry"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry">
+ <property name="eidasAttributesFile"
+ ref="specificConnectorAttributesFileWithPath" />
+ <property name="additionalAttributesFile"
+ ref="specificConnectorAdditionalAttributesFileWithPath" />
+ </bean>
+
+ <bean id="EIDPostProcessingService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.CcSpecificEidProcessingService" />
+
+ <bean id="DE-PostProcessor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeEidProcessor">
+ <property name="priority" value="1" />
+ </bean>
+
+ <bean id="LU-PostProcessor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.LuEidProcessor">
+ <property name="priority" value="1" />
+ </bean>
+
+ <bean id="NL-Processor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.NlEidProcessor">
+ <property name="priority" value="1" />
+ </bean>
+
+ <bean id="eIDASAuthModule"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasAuthenticationModulImpl">
+ <property name="priority" value="2" />
+ </bean>
+
+ <bean id="Default-PostProcessor"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.GenericEidProcessor">
+ <property name="priority" value="0" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml
new file mode 100644
index 00000000..6d6bb51e
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml
@@ -0,0 +1,67 @@
+<?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"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ 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
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+ <context:annotation-config />
+ <mvc:annotation-driven />
+ <mvc:default-servlet-handler />
+
+
+ <import resource="SpringTest-context_authManager.xml" />
+ <import resource="SpringTest-context_basic_test.xml" />
+
+ <bean id="mvcGUIBuilderImpl"
+ class="at.gv.egiz.eaaf.core.impl.gui.builder.SpringMvcGuiFormBuilderImpl" />
+
+ <bean id="springManagedSpecificConnectorCommunicationService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService" />
+
+ <bean id="specificConnectorAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/eidas-attributes.xml" />
+ </bean>
+
+ <bean id="specificConnectorAdditionalAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/additional-attributes.xml" />
+ </bean>
+
+ <bean id="attributeRegistry"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry">
+ <property name="eidasAttributesFile"
+ ref="specificConnectorAttributesFileWithPath" />
+ <property name="additionalAttributesFile"
+ ref="specificConnectorAdditionalAttributesFileWithPath" />
+ </bean>
+
+ <bean id="authBlockSigningService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService" />
+
+ <bean id="EidasSignalServlet"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet" />
+
+ <!-- Authentication Process Tasks -->
+ <bean id="ConnecteIDASNodeTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateAuthnRequestTask"
+ scope="prototype" />
+
+ <bean id="ReceiveResponseFromeIDASNodeTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAuthnResponseTask"
+ scope="prototype" />
+
+ <bean id="CreateIdentityLinkTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask"
+ scope="prototype" />
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/additional-attributes.xml b/modules/authmodule-eIDAS-v2/src/test/resources/config/additional-attributes.xml
new file mode 100644
index 00000000..6510546e
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/additional-attributes.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# Copyright (c) 2017 European Commission
+# 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/page/eupl-text-11-12
+# *
+# 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.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>Dynamic attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/AdditionalAttribute</entry>
+ <entry key="1.FriendlyName">AdditionalAttribute</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">false</entry>
+ <entry key="1.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="1.XmlType.LocalPart">string</entry>
+ <entry key="1.XmlType.NamespacePrefix">xs</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalAdditionalAttribute</entry>
+ <entry key="2.FriendlyName">LegalAdditionalAttribute</entry>
+ <entry key="2.PersonType">LegalPerson</entry>
+ <entry key="2.Required">false</entry>
+ <entry key="2.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="2.XmlType.LocalPart">string</entry>
+ <entry key="2.XmlType.NamespacePrefix">xs</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+</properties>
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/eidas-attributes.xml b/modules/authmodule-eIDAS-v2/src/test/resources/config/eidas-attributes.xml
new file mode 100644
index 00000000..cbae35db
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/eidas-attributes.xml
@@ -0,0 +1,376 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# Copyright (c) 2017 European Commission
+# 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/page/eupl-text-11-12
+# *
+# 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.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>eIDAS attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier</entry>
+ <entry key="1.FriendlyName">PersonIdentifier</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">true</entry>
+ <entry key="1.UniqueIdentifier">true</entry>
+ <entry key="1.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="1.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="1.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</entry>
+ <entry key="2.FriendlyName">FamilyName</entry>
+ <entry key="2.PersonType">NaturalPerson</entry>
+ <entry key="2.Required">true</entry>
+ <entry key="2.TransliterationMandatory">true</entry>
+ <entry key="2.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="2.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="2.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="3.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</entry>
+ <entry key="3.FriendlyName">FirstName</entry>
+ <entry key="3.PersonType">NaturalPerson</entry>
+ <entry key="3.Required">true</entry>
+ <entry key="3.TransliterationMandatory">true</entry>
+ <entry key="3.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="3.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="3.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="3.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="4.NameUri">http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</entry>
+ <entry key="4.FriendlyName">DateOfBirth</entry>
+ <entry key="4.PersonType">NaturalPerson</entry>
+ <entry key="4.Required">true</entry>
+ <entry key="4.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="4.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="4.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="4.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="5.NameUri">http://eidas.europa.eu/attributes/naturalperson/BirthName</entry>
+ <entry key="5.FriendlyName">BirthName</entry>
+ <entry key="5.PersonType">NaturalPerson</entry>
+ <entry key="5.Required">false</entry>
+ <entry key="5.TransliterationMandatory">true</entry>
+ <entry key="5.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="5.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="5.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="5.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="6.NameUri">http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth</entry>
+ <entry key="6.FriendlyName">PlaceOfBirth</entry>
+ <entry key="6.PersonType">NaturalPerson</entry>
+ <entry key="6.Required">false</entry>
+ <entry key="6.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="6.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="6.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="6.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="7.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentAddress</entry>
+ <entry key="7.FriendlyName">CurrentAddress</entry>
+ <entry key="7.PersonType">NaturalPerson</entry>
+ <entry key="7.Required">false</entry>
+ <entry key="7.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="7.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="7.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="7.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.CurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="8.NameUri">http://eidas.europa.eu/attributes/naturalperson/Gender</entry>
+ <entry key="8.FriendlyName">Gender</entry>
+ <entry key="8.PersonType">NaturalPerson</entry>
+ <entry key="8.Required">false</entry>
+ <entry key="8.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="8.XmlType.LocalPart">GenderType</entry>
+ <entry key="8.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="8.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="9.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier</entry>
+ <entry key="9.FriendlyName">LegalPersonIdentifier</entry>
+ <entry key="9.PersonType">LegalPerson</entry>
+ <entry key="9.Required">true</entry>
+ <entry key="9.UniqueIdentifier">true</entry>
+ <entry key="9.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="9.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="9.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="9.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="10.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalName</entry>
+ <entry key="10.FriendlyName">LegalName</entry>
+ <entry key="10.PersonType">LegalPerson</entry>
+ <entry key="10.Required">true</entry>
+ <entry key="10.TransliterationMandatory">true</entry>
+ <entry key="10.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="10.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="10.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="10.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="11.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonAddress</entry>
+ <entry key="11.FriendlyName">LegalAddress</entry>
+ <entry key="11.PersonType">LegalPerson</entry>
+ <entry key="11.Required">false</entry>
+ <entry key="11.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="11.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="11.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="11.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.LegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="12.NameUri">http://eidas.europa.eu/attributes/legalperson/VATRegistrationNumber</entry>
+ <entry key="12.FriendlyName">VATRegistration</entry>
+ <entry key="12.PersonType">LegalPerson</entry>
+ <entry key="12.Required">false</entry>
+ <entry key="12.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="12.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="12.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="12.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="13.NameUri">http://eidas.europa.eu/attributes/legalperson/TaxReference</entry>
+ <entry key="13.FriendlyName">TaxReference</entry>
+ <entry key="13.PersonType">LegalPerson</entry>
+ <entry key="13.Required">false</entry>
+ <entry key="13.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="13.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="13.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="13.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="14.NameUri">http://eidas.europa.eu/attributes/legalperson/D-2012-17-EUIdentifier</entry>
+ <entry key="14.FriendlyName">D-2012-17-EUIdentifier</entry>
+ <entry key="14.PersonType">LegalPerson</entry>
+ <entry key="14.Required">false</entry>
+ <entry key="14.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="14.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="14.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="14.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="15.NameUri">http://eidas.europa.eu/attributes/legalperson/LEI</entry>
+ <entry key="15.FriendlyName">LEI</entry>
+ <entry key="15.PersonType">LegalPerson</entry>
+ <entry key="15.Required">false</entry>
+ <entry key="15.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="15.XmlType.LocalPart">LEIType</entry>
+ <entry key="15.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="15.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="16.NameUri">http://eidas.europa.eu/attributes/legalperson/EORI</entry>
+ <entry key="16.FriendlyName">EORI</entry>
+ <entry key="16.PersonType">LegalPerson</entry>
+ <entry key="16.Required">false</entry>
+ <entry key="16.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="16.XmlType.LocalPart">EORIType</entry>
+ <entry key="16.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="16.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="17.NameUri">http://eidas.europa.eu/attributes/legalperson/SEED</entry>
+ <entry key="17.FriendlyName">SEED</entry>
+ <entry key="17.PersonType">LegalPerson</entry>
+ <entry key="17.Required">false</entry>
+ <entry key="17.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="17.XmlType.LocalPart">SEEDType</entry>
+ <entry key="17.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="17.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="18.NameUri">http://eidas.europa.eu/attributes/legalperson/SIC</entry>
+ <entry key="18.FriendlyName">SIC</entry>
+ <entry key="18.PersonType">LegalPerson</entry>
+ <entry key="18.Required">false</entry>
+ <entry key="18.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="18.XmlType.LocalPart">SICType</entry>
+ <entry key="18.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="18.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="19.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PersonIdentifier</entry>
+ <entry key="19.FriendlyName">RepresentativePersonIdentifier</entry>
+ <entry key="19.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="19.Required">false</entry>
+ <entry key="19.UniqueIdentifier">true</entry>
+ <entry key="19.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="19.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="19.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="19.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="20.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentFamilyName</entry>
+ <entry key="20.FriendlyName">RepresentativeFamilyName</entry>
+ <entry key="20.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="20.Required">false</entry>
+ <entry key="20.TransliterationMandatory">true</entry>
+ <entry key="20.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="20.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="20.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="20.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="21.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentGivenName</entry>
+ <entry key="21.FriendlyName">RepresentativeFirstName</entry>
+ <entry key="21.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="21.Required">false</entry>
+ <entry key="21.TransliterationMandatory">true</entry>
+ <entry key="21.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="21.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="21.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="21.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="22.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/DateOfBirth</entry>
+ <entry key="22.FriendlyName">RepresentativeDateOfBirth</entry>
+ <entry key="22.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="22.Required">false</entry>
+ <entry key="22.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="22.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="22.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="22.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="23.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/BirthName</entry>
+ <entry key="23.FriendlyName">RepresentativeBirthName</entry>
+ <entry key="23.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="23.Required">false</entry>
+ <entry key="23.TransliterationMandatory">true</entry>
+ <entry key="23.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="23.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="23.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="23.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="24.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PlaceOfBirth</entry>
+ <entry key="24.FriendlyName">RepresentativePlaceOfBirth</entry>
+ <entry key="24.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="24.Required">false</entry>
+ <entry key="24.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="24.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="24.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="24.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="25.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentAddress</entry>
+ <entry key="25.FriendlyName">RepresentativeCurrentAddress</entry>
+ <entry key="25.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="25.Required">false</entry>
+ <entry key="25.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="25.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="25.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="25.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvCurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="26.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/Gender</entry>
+ <entry key="26.FriendlyName">RepresentativeGender</entry>
+ <entry key="26.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="26.Required">false</entry>
+ <entry key="26.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="26.XmlType.LocalPart">GenderType</entry>
+ <entry key="26.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="26.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="27.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonIdentifier</entry>
+ <entry key="27.FriendlyName">RepresentativeLegalPersonIdentifier</entry>
+ <entry key="27.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="27.Required">false</entry>
+ <entry key="27.UniqueIdentifier">true</entry>
+ <entry key="27.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="27.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="27.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="27.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="28.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalName</entry>
+ <entry key="28.FriendlyName">RepresentativeLegalName</entry>
+ <entry key="28.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="28.Required">false</entry>
+ <entry key="28.TransliterationMandatory">true</entry>
+ <entry key="28.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="28.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="28.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="28.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="29.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="29.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="29.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="29.Required">false</entry>
+ <entry key="29.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="29.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="29.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="29.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="30.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="30.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="30.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="30.Required">false</entry>
+ <entry key="30.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="30.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="30.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="30.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="31.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/TaxReference</entry>
+ <entry key="31.FriendlyName">RepresentativeTaxReference</entry>
+ <entry key="31.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="31.Required">false</entry>
+ <entry key="31.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="31.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="31.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="31.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="32.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/D-2012-17-EUIdentifier</entry>
+ <entry key="32.FriendlyName">RepresentativeD-2012-17-EUIdentifier</entry>
+ <entry key="32.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="32.Required">false</entry>
+ <entry key="32.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="32.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="32.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="32.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="33.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LEI</entry>
+ <entry key="33.FriendlyName">RepresentativeLEI</entry>
+ <entry key="33.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="33.Required">false</entry>
+ <entry key="33.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="33.XmlType.LocalPart">LEIType</entry>
+ <entry key="33.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="33.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="34.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/EORI</entry>
+ <entry key="34.FriendlyName">RepresentativeEORI</entry>
+ <entry key="34.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="34.Required">false</entry>
+ <entry key="34.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="34.XmlType.LocalPart">EORIType</entry>
+ <entry key="34.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="34.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="35.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SEED</entry>
+ <entry key="35.FriendlyName">RepresentativeSEED</entry>
+ <entry key="35.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="35.Required">false</entry>
+ <entry key="35.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="35.XmlType.LocalPart">SEEDType</entry>
+ <entry key="35.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="35.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="36.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SIC</entry>
+ <entry key="36.FriendlyName">RepresentativeSIC</entry>
+ <entry key="36.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="36.Required">false</entry>
+ <entry key="36.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="36.XmlType.LocalPart">SICType</entry>
+ <entry key="36.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="36.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="39.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="39.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="39.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="39.Required">false</entry>
+ <entry key="39.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="39.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="39.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="39.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="40.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="40.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="40.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="40.Required">false</entry>
+ <entry key="40.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="40.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="40.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="40.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+
+</properties>
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties
new file mode 100644
index 00000000..a662379c
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties
@@ -0,0 +1,117 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=
+eidas.ms.context.url.request.validation=false
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=
+eidas.ms.auth.eIDAS.node_v2.forward.method=POST
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true
+eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs=myNode
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.8=testtest,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.path=keys/.....
+eidas.ms.pvp2.keystore.password=
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=
+eidas.ms.sp.0.pvp2.metadata.truststore=
+eidas.ms.sp.0.pvp2.metadata.truststore.password=
+eidas.ms.sp.0.newEidMode=true
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties
new file mode 100644
index 00000000..7c5e5a40
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties
@@ -0,0 +1,114 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=
+eidas.ms.context.url.request.validation=false
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://test
+eidas.ms.auth.eIDAS.node_v2.forward.method=GET
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+#eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=false
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.7=CurrentAddress,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.path=keys/.....
+eidas.ms.pvp2.keystore.password=
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=
+eidas.ms.sp.0.pvp2.metadata.truststore=
+eidas.ms.sp.0.pvp2.metadata.truststore.password=
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties
new file mode 100644
index 00000000..c830d447
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties
@@ -0,0 +1,118 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=
+eidas.ms.context.url.request.validation=false
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://test.com/
+eidas.ms.auth.eIDAS.node_v2.forward.method=POST
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true
+eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs=myNode
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.8=testtest,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.path=keys/.....
+eidas.ms.pvp2.keystore.password=
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=
+eidas.ms.sp.0.pvp2.metadata.truststore=
+eidas.ms.sp.0.pvp2.metadata.truststore.password=
+eidas.ms.sp.0.newEidMode=true
+
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_4.properties b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_4.properties
new file mode 100644
index 00000000..01e72069
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_4.properties
@@ -0,0 +1,114 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=
+eidas.ms.context.url.request.validation=false
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://test
+eidas.ms.auth.eIDAS.node_v2.forward.method=GET
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+#eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=false
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=false
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.7=CurrentAddress,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.path=keys/.....
+eidas.ms.pvp2.keystore.password=
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=
+eidas.ms.sp.0.pvp2.metadata.truststore=
+eidas.ms.sp.0.pvp2.metadata.truststore.password=
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties
new file mode 100644
index 00000000..6b235667
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties
@@ -0,0 +1,116 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=
+eidas.ms.context.url.request.validation=false
+eidas.ms.core.configRootDir=file:./src/test/resources/config/
+
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://test
+eidas.ms.auth.eIDAS.node_v2.forward.method=GET
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+#eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.path=keys/.....
+eidas.ms.pvp2.keystore.password=
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=
+eidas.ms.sp.0.pvp2.metadata.truststore=
+eidas.ms.sp.0.pvp2.metadata.truststore.password=
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/junit.jks b/modules/authmodule-eIDAS-v2/src/test/resources/data/junit.jks
new file mode 100644
index 00000000..a18df332
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/junit.jks
Binary files differ
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/signed_eidasBind.jws b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/signed_eidasBind.jws
new file mode 100644
index 00000000..f7c9a1c7
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/signed_eidasBind.jws
@@ -0,0 +1 @@
+eyJ1cm46YXQuZ3YuZWlkOmJpbmR0eXBlIjoidXJuOmF0Lmd2LmVpZDplaWRhc0JpbmQiLCJhbGciOiJSUzUxMiIsIng1dCNTMjU2IjoiY3FtcXBHdWlnS0NRelVWX1doWURHU1EyNEx6Zkxtd0ZtUlNYQlNYR3o3byJ9.eyJ1cm46ZWlkZ3ZhdDphdHRyaWJ1dGVzLnZzei52YWx1ZSI6IjhEYWNBTUxVSFEiLCJ1cm46ZWlkZ3ZhdDphdHRyaWJ1dGVzLnVzZXIucHVia2V5cyI6WyI1NDZ5OEtXZ3R1V3F1dXVNdC9DUWhKem1pWXZ3bzR1QzhLZWxxdUtMc2VLbG1mQ2dtcnpscGFQd3A1K3Q2NjI4Il0sInVybjplaWRndmF0OmF0dHJpYnV0ZXMuZWlkLnN0YXR1cyI6InVybjplaWRndmF0OmVpZC5zdGF0dXMuZWlkYXMifQ.WiECS-E5RB-zQV3JW6-3B7op093QErqq3yS2S4YVFQq9XmYzTD8UKo63yaHa-2U2WFUbiwNI3OOkwNZIAedMZHHblZ0jzjGTb58zL4Yvm6sPSlq3TP5u0emiQdjIJNQmILE5ZYVOgSA-4MWLXAgRQEl2A1w8lHxptE6ya83GdhA0gP51-rY_536qvVuaZHrQ2Lpahl-lTIY1Zi6Knqj1yFdH-auqkLxB44l-XvMv9QryBZMAkkmiu8J598rzIJ2ifGyw4UqHDJZ53GKUpBbU_X23ZjsZ8B5ZapRTO9JGoEEW3rMDEO5_9cjWYOCn87-CA3bMNVbo1KN146UZGuZbyXuevLPznRkbCtXS--IE0SuuLBaowcktX2ggeeSzaq6UZW7hSmQnErVgxxfP16ijBu8yylo-PFbqgYFNT-Ca2rS8i1Cs0KdPTahYIRm4xLARahYLQbqA15medm7JSoz4tA468c_hcNzyG9aGoXYuw1F5kUrJkHl0IWdHkvSR8RWw \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_error_travelerdocexists.xml b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_error_travelerdocexists.xml
new file mode 100644
index 00000000..d627ded2
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_error_travelerdocexists.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Fault xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
+ <faultcode xmlns:p344="urn:SZRServices" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">p344:F455</faultcode>
+ <faultstring>The travel document you sent to insert a person already exists for another person. Either check the document or have the person altered accordingly</faultstring>
+ <faultactor>urn:SZRServices</faultactor>
+</SOAP-ENV:Fault>
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_1.xml b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_1.xml
new file mode 100644
index 00000000..c376caef
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_1.xml
@@ -0,0 +1,50 @@
+<ns6:GetIdentityLinkEidasResponse xmlns="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:ns2="http://egov.gv.at/pvp1.xsd" xmlns:ns3="http://www.w3.org/2000/09/xmldsig#" xmlns:ns4="http://www.w3.org/2001/04/xmldsig-more#" xmlns:ns5="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:ns6="urn:SZRServices"><ns6:GetIdentityLinkReturn><ns6:PersonInfo><ns6:Person><Identification><Value>k+zDM1BVpN1WJO4x7ZQ3ng==</Value><Type>urn:publicid:gv.at:baseid</Type></Identification><Name><GivenName>Franz</GivenName><FamilyName>Mustermann</FamilyName></Name><Sex>unknown</Sex><DateOfBirth>1989-05-05</DateOfBirth></ns6:Person></ns6:PersonInfo><ns6:Assertion><saml:Assertion xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID15650069652921" IssueInstant="2019-08-05T14:09:25+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0">
+ <saml:AttributeStatement>
+ <saml:Subject>
+ <saml:SubjectConfirmation>
+ <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod>
+ <saml:SubjectConfirmationData>
+ <pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>k+zDM1BVpN1WJO4x7ZQ3ng==</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type></pr:Identification><pr:Name><pr:GivenName>Hans</pr:GivenName><pr:FamilyName primary="undefined">Mustermann</pr:FamilyName></pr:Name><pr:DateOfBirth>1989-05-05</pr:DateOfBirth></pr:Person>
+ </saml:SubjectConfirmationData>
+ </saml:SubjectConfirmation>
+ </saml:Subject>
+ </saml:AttributeStatement>
+ <dsig:Signature>
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath>
+ </dsig:Transform>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>GZjlsEXIhUPBSbOR1R8P4dzRJHE=</dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest">
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>lCnWsFICFg0ogj0Ha7++Y9gyOQg=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue>
+ a6tPfkdriEzAyQh2jU3/4j48baaPnY/i510OHx0vwHRvXLz80UyZzffdmtaRuk3iHVxgUMd9
+ Ld0DLsRt6tFJiPLyBCo0QCuqaOwgTcuUI3Ku/oySpqMjqug3AMdrhxW2j41yQlzvkjiZTT4j
+ zQ9GHFnZnnob0+bBflqIjZOl4xc=
+ </dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIICTzCCAbigAwIBAgIBADANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhTWlJQRVJTQjAeFw0wNTA3MDEwMDAwMDBaFw00MDEyMzEyMzU5NTlaMBMxETAPBgNVBAMTCFNaUlBFUlNCMIIBHzANBgkqhkiG9w0BAQEFAAOCAQwAMIIBBwKBgQDGNmo9LOohefioGreKU6j6R05jUwHuddziSOQPolmMSXQG6NnnlLQaITv7BEmFj+EBqaOc+891wgZCRvNA2h+fHdJ69QXi/xjCovJI5SHh9jA+ssqhZ68iXOZHPq4WeegtYiYyJaRxWF+iPLqSm+bknS/KuBUcZol9SM3r6CMf0wKBgHytGrIelzc9ZN97VYXLkOJxi4TNSSj3Q/1TIC0s+HSzjbD694Y6ufINpR+IQm5epLTdXx9Dxv19bYnsLEIt0niMd2Cnm1DxXe8iNaDzpWec7fbRT6vDBwtTnyQkGfu2GGF3nSvVZ5AUDbLdAfZLOlbwsZmPnWU1zktSkLgKnT2XozIwMDAuBglghkgBhvhCAQ0EIRMfQ3JlYXRlZCBieSB6L09TIElDU0YgLSBIQ1I3NzgwIDANBgkqhkiG9w0BAQUFAAOBgQBwPc3l/Qf4myH8rsAAM5HqdCR68bMegWgNVxlPNl5DNJEE2hbPhIJ/K6TF6cjROYKDVuQ/+drtsZcrEOaqhqD3qw7MXAiT9GurV99YM/qTBsMy13yjU3LqeFX25Om8JlccGF5G+iHrVjfNQEUocGnGxCAPMlBvGwia4JjJcIPx7Q==</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo>
+ <dsig:Object>
+ <dsig:Manifest Id="manifest">
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>SbpaaSlLolEX5D9P7HyTPnImvns=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:Manifest>
+ </dsig:Object>
+ </dsig:Signature>
+</saml:Assertion></ns6:Assertion><ns6:AdditionalInfo>ERN</ns6:AdditionalInfo></ns6:GetIdentityLinkReturn></ns6:GetIdentityLinkEidasResponse> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_2.xml b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_2.xml
new file mode 100644
index 00000000..f07c67d6
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/data/szr/szr_resp_valid_2.xml
@@ -0,0 +1,50 @@
+<ns6:GetIdentityLinkEidasResponse xmlns="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:ns2="http://egov.gv.at/pvp1.xsd" xmlns:ns3="http://www.w3.org/2000/09/xmldsig#" xmlns:ns4="http://www.w3.org/2001/04/xmldsig-more#" xmlns:ns5="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:ns6="urn:SZRServices"><ns6:GetIdentityLinkReturn><ns6:PersonInfo><ns6:Person><Identification><Value>k+zDM1BVpN1WJO4x7ZQ3ng==</Value><Type>urn:publicid:gv.at:baseid</Type></Identification><Name><GivenName>Franz</GivenName><FamilyName>Mustermann</FamilyName></Name><Sex>unknown</Sex><DateOfBirth>1989-05-05</DateOfBirth></ns6:Person></ns6:PersonInfo><ns6:Assertion><saml:Assertion xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID15650069652921" IssueInstant="2019-08-05T14:09:25+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0">
+ <saml:AttributeStatement>
+ <saml:Subject>
+ <saml:SubjectConfirmation>
+ <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod>
+ <saml:SubjectConfirmationData>
+ <pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>k+zDM1BV1312312332x7ZQ3ng==</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type></pr:Identification><pr:Name><pr:GivenName>Martina</pr:GivenName><pr:FamilyName primary="undefined">Musterfrau</pr:FamilyName></pr:Name><pr:DateOfBirth>1991-04-15</pr:DateOfBirth></pr:Person>
+ </saml:SubjectConfirmationData>
+ </saml:SubjectConfirmation>
+ </saml:Subject>
+ </saml:AttributeStatement>
+ <dsig:Signature>
+ <dsig:SignedInfo>
+ <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath>
+ </dsig:Transform>
+ <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>GZjlsEXIhUPBSbOR1R8P4dzRJHE=</dsig:DigestValue>
+ </dsig:Reference>
+ <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest">
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>lCnWsFICFg0ogj0Ha7++Y9gyOQg=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:SignedInfo>
+ <dsig:SignatureValue>
+ a6tPfkdriEzAyQh2jU3/4j48baaPnY/i510OHx0vwHRvXLz80UyZzffdmtaRuk3iHVxgUMd9
+ Ld0DLsRt6tFJiPLyBCo0QCuqaOwgTcuUI3Ku/oySpqMjqug3AMdrhxW2j41yQlzvkjiZTT4j
+ zQ9GHFnZnnob0+bBflqIjZOl4xc=
+ </dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIICTzCCAbigAwIBAgIBADANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhTWlJQRVJTQjAeFw0wNTA3MDEwMDAwMDBaFw00MDEyMzEyMzU5NTlaMBMxETAPBgNVBAMTCFNaUlBFUlNCMIIBHzANBgkqhkiG9w0BAQEFAAOCAQwAMIIBBwKBgQDGNmo9LOohefioGreKU6j6R05jUwHuddziSOQPolmMSXQG6NnnlLQaITv7BEmFj+EBqaOc+891wgZCRvNA2h+fHdJ69QXi/xjCovJI5SHh9jA+ssqhZ68iXOZHPq4WeegtYiYyJaRxWF+iPLqSm+bknS/KuBUcZol9SM3r6CMf0wKBgHytGrIelzc9ZN97VYXLkOJxi4TNSSj3Q/1TIC0s+HSzjbD694Y6ufINpR+IQm5epLTdXx9Dxv19bYnsLEIt0niMd2Cnm1DxXe8iNaDzpWec7fbRT6vDBwtTnyQkGfu2GGF3nSvVZ5AUDbLdAfZLOlbwsZmPnWU1zktSkLgKnT2XozIwMDAuBglghkgBhvhCAQ0EIRMfQ3JlYXRlZCBieSB6L09TIElDU0YgLSBIQ1I3NzgwIDANBgkqhkiG9w0BAQUFAAOBgQBwPc3l/Qf4myH8rsAAM5HqdCR68bMegWgNVxlPNl5DNJEE2hbPhIJ/K6TF6cjROYKDVuQ/+drtsZcrEOaqhqD3qw7MXAiT9GurV99YM/qTBsMy13yjU3LqeFX25Om8JlccGF5G+iHrVjfNQEUocGnGxCAPMlBvGwia4JjJcIPx7Q==</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo>
+ <dsig:Object>
+ <dsig:Manifest Id="manifest">
+ <dsig:Reference URI="">
+ <dsig:Transforms>
+ <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
+ <dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath>
+ </dsig:Transform>
+ </dsig:Transforms>
+ <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <dsig:DigestValue>SbpaaSlLolEX5D9P7HyTPnImvns=</dsig:DigestValue>
+ </dsig:Reference>
+ </dsig:Manifest>
+ </dsig:Object>
+ </dsig:Signature>
+</saml:Assertion></ns6:Assertion><ns6:AdditionalInfo>ERN</ns6:AdditionalInfo></ns6:GetIdentityLinkReturn></ns6:GetIdentityLinkEidasResponse> \ No newline at end of file
diff --git a/modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jks b/modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jks
new file mode 100644
index 00000000..fcc6400c
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jks
Binary files differ
diff --git a/modules/authmodule_id-austria/checks/spotbugs-exclude.xml b/modules/authmodule_id-austria/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..366c7aca
--- /dev/null
+++ b/modules/authmodule_id-austria/checks/spotbugs-exclude.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+ <Match>
+ <!-- CSRF protection is implicit available by request token -->
+ <Class name="at.asitplus.eidas.specific.modules.auth.idaustria.controller.IdAustriaAuthSignalController" />
+ <Method name="performEidasAuthentication" />
+ <OR>
+ <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" />
+ </OR>
+ </Match>
+ <!-- Logging of invalid SAML2 responses are allowed on debug level -->
+ <Match>
+ <Class name="at.asitplus.eidas.specific.modules.auth.idaustria.tasks.ReceiveFromIdAustriaSystemTask"/>
+ <Method name="execute" />
+ <OR>
+ <Bug pattern="CRLF_INJECTION_LOGS" />
+ </OR>
+ </Match>
+ <Match>
+ <!-- Builder pattern does not expose date elements -->
+ <OR>
+ <Class name="at.asitplus.eidas.specific.modules.auth.idaustria.config.IdAustriaAuthRequestBuilderConfiguration" />
+ </OR>
+ <OR>
+ <Bug pattern="EI_EXPOSE_REP" />
+ <Bug pattern="EI_EXPOSE_REP2" />
+ </OR>
+ </Match>
+</FindBugsFilter>
diff --git a/modules/authmodule_id-austria/pom.xml b/modules/authmodule_id-austria/pom.xml
new file mode 100644
index 00000000..1afa71df
--- /dev/null
+++ b/modules/authmodule_id-austria/pom.xml
@@ -0,0 +1,171 @@
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>authmodule_id-austria</artifactId>
+ <name>ID-Austria authentication</name>
+ <description>User authentication forwarding user to ID Austria system</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz.components</groupId>
+ <artifactId>egiz-spring-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>eidas_proxy-sevice</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_sp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</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>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </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>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_idp</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+
+<build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs-maven-plugin</artifactId>
+ <version>${spotbugs-maven-plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>post-unit-check</id>
+ <phase>test</phase>
+ <goals>
+ <goal>check</goal>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <haltOnFailure>true</haltOnFailure>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- enable co-existence of testng and junit -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <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/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java
new file mode 100644
index 00000000..57e5c706
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java
@@ -0,0 +1,123 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+
+/**
+ * Constant values for ID Austria authentication module.
+ *
+ * @author tlenz
+ *
+ */
+public class IdAustriaAuthConstants {
+
+ private IdAustriaAuthConstants() {
+
+ }
+
+ public static final String ERRORTYPE_00 = "module.idaustria.00";
+ public static final String ERRORTYPE_01 = "module.idaustria.01";
+ public static final String ERRORTYPE_02 = "module.idaustria.02";
+ public static final String ERRORTYPE_03 = "module.idaustria.03";
+ public static final String ERRORTYPE_04 = "module.idaustria.04";
+ public static final String ERRORTYPE_05 = "module.idaustria.05";
+ public static final String ERRORTYPE_06 = "module.idaustria.06";
+ public static final String ERRORTYPE_98 = "module.idaustria.98";
+ public static final String ERRORTYPE_99 = "module.idaustria.99";
+
+
+ public static final String SAML2_STATUSCODE_USERSTOP = "1005";
+
+ public static final int METADATA_VALIDUNTIL_IN_HOURS = 24 * 365;
+ public static final String MODULE_NAME_FOR_LOGGING = "ID Austria based eIDAS authentication";
+
+ public static final String ENDPOINT_POST = "/sp/idaustria/eidas/post";
+ public static final String ENDPOINT_REDIRECT = "/sp/idaustria/eidas/redirect";
+ public static final String ENDPOINT_METADATA = "/sp/idaustria/eidas/metadata";
+
+ public static final String CONFIG_PROPS_PREFIX = "modules.idaustriaauth.";
+
+ public static final String CONFIG_PROPS_IDAUSTRIA_ENTITYID = CONFIG_PROPS_PREFIX + "idp.entityId";
+ public static final String CONFIG_PROPS_IDAUSTRIA_METADATAURL = CONFIG_PROPS_PREFIX + "idp.metadataUrl";
+
+ public static final String CONFIG_PROPS_KEYSTORE_TYPE = CONFIG_PROPS_PREFIX + "keystore.type";
+ public static final String CONFIG_PROPS_KEYSTORE_NAME = CONFIG_PROPS_PREFIX + "keystore.name";
+ public static final String CONFIG_PROPS_KEYSTORE_PATH = CONFIG_PROPS_PREFIX + "keystore.path";
+ public static final String CONFIG_PROPS_KEYSTOREPASSWORD = CONFIG_PROPS_PREFIX + "keystore.password";
+ public static final String CONFIG_PROPS_SIGN_METADATA_KEY_PASSWORD = CONFIG_PROPS_PREFIX
+ + "metadata.sign.password";
+ public static final String CONFIG_PROPS_SIGN_METADATA_ALIAS = CONFIG_PROPS_PREFIX
+ + "metadata.sign.alias";
+ public static final String CONFIG_PROPS_SIGN_SIGNING_KEY_PASSWORD = CONFIG_PROPS_PREFIX
+ + "request.sign.password";
+ public static final String CONFIG_PROPS_SIGN_SIGNING_ALIAS = CONFIG_PROPS_PREFIX
+ + "request.sign.alias";
+ public static final String CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD = CONFIG_PROPS_PREFIX
+ + "response.encryption.password";
+ public static final String CONFIG_PROPS_ENCRYPTION_ALIAS = CONFIG_PROPS_PREFIX
+ + "response.encryption.alias";
+
+ public static final String CONFIG_PROPS_TRUSTSTORE_TYPE = CONFIG_PROPS_PREFIX + "truststore.type";
+ public static final String CONFIG_PROPS_TRUSTSTORE_NAME = CONFIG_PROPS_PREFIX + "truststore.name";
+ public static final String CONFIG_PROPS_TRUSTSTORE_PATH = CONFIG_PROPS_PREFIX + "truststore.path";
+ public static final String CONFIG_PROPS_TRUSTSTORE_PASSWORD = CONFIG_PROPS_PREFIX + "truststore.password";
+
+ public static final String CONFIG_PROPS_REQUIRED_PVP_ATTRIBUTES_LIST = CONFIG_PROPS_PREFIX
+ + "required.additional.attributes";
+
+
+ /**
+ * SP specific EntityId of the ID Austria.
+ */
+ public static final String CONFIG_PROPS_APPSPECIFIC_IDAUSTRIA_NODE_URL = "auth.idaustria.entityId";
+
+
+ public static final List<Triple<String, String, Boolean>> DEFAULT_REQUIRED_PVP_ATTRIBUTES =
+ Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ // add PVP Version attribute
+ add(Triple.newInstance(PvpAttributeDefinitions.PVP_VERSION_NAME,
+ PvpAttributeDefinitions.PVP_VERSION_FRIENDLY_NAME, false));
+
+ // entity information
+ add(Triple.newInstance(PvpAttributeDefinitions.GIVEN_NAME_NAME,
+ PvpAttributeDefinitions.GIVEN_NAME_FRIENDLY_NAME, true));
+ add(Triple.newInstance(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME,
+ PvpAttributeDefinitions.PRINCIPAL_NAME_FRIENDLY_NAME, true));
+ add(Triple.newInstance(PvpAttributeDefinitions.BIRTHDATE_NAME,
+ PvpAttributeDefinitions.BIRTHDATE_FRIENDLY_NAME, true));
+ add(Triple.newInstance(PvpAttributeDefinitions.BPK_NAME,
+ PvpAttributeDefinitions.BPK_FRIENDLY_NAME, true));
+
+ // entity metadata information
+ add(Triple.newInstance(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME,
+ PvpAttributeDefinitions.EID_ISSUING_NATION_FRIENDLY_NAME, true));
+ add(Triple.newInstance(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME,
+ PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, false));
+
+ // mandate attributes
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_TYPE_NAME,
+ PvpAttributeDefinitions.MANDATE_TYPE_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_TYPE_OID_NAME,
+ PvpAttributeDefinitions.MANDATE_TYPE_OID_FRIENDLY_NAME, false));
+ addAll(MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_JUR_PVP_ATTRIBUTES);
+ addAll(MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_NAT_PVP_ATTRIBUTES);
+
+ }
+ });
+
+ public static final Set<String> DEFAULT_REQUIRED_PVP_ATTRIBUTE_NAMES =
+ DEFAULT_REQUIRED_PVP_ATTRIBUTES.stream()
+ .filter(el -> el.getThird())
+ .map(el -> el.getFirst())
+ .collect(Collectors.toSet());
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthenticationSpringResourceProvider.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthenticationSpringResourceProvider.java
new file mode 100644
index 00000000..2240b843
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthenticationSpringResourceProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.idaustria;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+public class IdAustriaAuthenticationSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "Auth. module for ID Austria based authentication";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ return null;
+
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource idAustriaAuthConfig =
+ new ClassPathResource("/spring/id_austria_auth.beans.xml",
+ IdAustriaAuthenticationSpringResourceProvider.class);
+ final ClassPathResource idAustriaTaskConfig =
+ new ClassPathResource("/spring/id_austria_task.beans.xml",
+ IdAustriaAuthenticationSpringResourceProvider.class);
+
+ return new Resource[] { idAustriaAuthConfig, idAustriaTaskConfig };
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaEidasProxyAuthenticationModulImpl.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaEidasProxyAuthenticationModulImpl.java
new file mode 100644
index 00000000..6f90569c
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaEidasProxyAuthenticationModulImpl.java
@@ -0,0 +1,91 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.idaustria;
+
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Authentication-process selection to start ID Austria authentication for eIDAS Proxy-Service requests.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class IdAustriaEidasProxyAuthenticationModulImpl implements AuthModule {
+
+ private static final String ID_AUSTRIA_EIDAS_PROXY_AUTHPROCESS_NAME = "idAustriaForEidasProxyService";
+
+ private int priority = 1;
+
+ @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;
+ }
+
+ /*
+ * (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) {
+ if (pendingReq instanceof ProxyServicePendingRequest) {
+ log.info("Find eIDAS Proxy-Service request. Starting ID Austria based user authentication ... ");
+ return ID_AUSTRIA_EIDAS_PROXY_AUTHPROCESS_NAME;
+
+ } else {
+ log.trace("No {} request. Ignore it for ID Austria authentication",
+ ProxyServicePendingRequest.class.getName());
+
+ }
+
+ return null;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()
+ */
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:/process/id_austria.Authentication.process.xml" };
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/EidasConnecorUniqueIdAttributeBuilder.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/EidasConnecorUniqueIdAttributeBuilder.java
new file mode 100644
index 00000000..89e06991
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/EidasConnecorUniqueIdAttributeBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * 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.asitplus.eidas.specific.modules.auth.idaustria.builder.attributes;
+
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+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;
+
+public class EidasConnecorUniqueIdAttributeBuilder
+ implements IAttributeBuilder, ExtendedPvpAttributeDefinitions {
+
+ @Override
+ public String getName() {
+ return EIDAS_CONNECTOR_UNIQUEID_NAME;
+ }
+
+ @Override
+ public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData,
+ final IAttributeGenerator<ATT> g)
+ throws AttributeBuilderException {
+ return g.buildStringAttribute(EIDAS_CONNECTOR_UNIQUEID_FRIENDLY_NAME, EIDAS_CONNECTOR_UNIQUEID_NAME,
+ oaParam.getUniqueIdentifier());
+
+ }
+
+ @Override
+ public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) {
+ return g.buildEmptyAttribute(EIDAS_CONNECTOR_UNIQUEID_FRIENDLY_NAME, EIDAS_CONNECTOR_UNIQUEID_NAME);
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMessageSource.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMessageSource.java
new file mode 100644
index 00000000..697c4496
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMessageSource.java
@@ -0,0 +1,22 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.config;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+/**
+ * i18n message-source for ID Austria authentication errors.
+ *
+ * @author tlenz
+ *
+ */
+public class IdAustriaAuthMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/idaustria_auth_messages");
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMetadataConfiguration.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMetadataConfiguration.java
new file mode 100644
index 00000000..41990363
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMetadataConfiguration.java
@@ -0,0 +1,462 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.Organization;
+import org.opensaml.saml.saml2.metadata.RequestedAttribute;
+import org.opensaml.security.credential.Credential;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Configuration object to generate PVP S-Profile metadata for SAML2 client.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class IdAustriaAuthMetadataConfiguration implements IPvpMetadataBuilderConfiguration {
+
+ private Collection<RequestedAttribute> additionalAttributes = null;
+
+ private final String authUrl;
+ private final IdAustriaAuthCredentialProvider credentialProvider;
+ private final IPvp2BasicConfiguration pvpConfiguration;
+
+ /**
+ * Configuration object to create PVP2 S-Profile metadata information.
+ *
+ * @param authUrl Public URL prefix of the application
+ * @param credentialProvider Credentials used by PVP2 S-Profile end-point
+ * @param pvpConfiguration Basic PVP2 S-Profile end-point configuration
+ */
+ public IdAustriaAuthMetadataConfiguration(String authUrl,
+ IdAustriaAuthCredentialProvider credentialProvider,
+ IPvp2BasicConfiguration pvpConfiguration) {
+ this.authUrl = authUrl;
+ this.credentialProvider = credentialProvider;
+ this.pvpConfiguration = pvpConfiguration;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getMetadataValidUntil()
+ */
+ @Override
+ public int getMetadataValidUntil() {
+ return IdAustriaAuthConstants.METADATA_VALIDUNTIL_IN_HOURS;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * buildEntitiesDescriptorAsRootElement()
+ */
+ @Override
+ public boolean buildEntitiesDescriptorAsRootElement() {
+ return false;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * buildIDPSSODescriptor()
+ */
+ @Override
+ public boolean buildIdpSsoDescriptor() {
+ return false;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * buildSPSSODescriptor()
+ */
+ @Override
+ public boolean buildSpSsoDescriptor() {
+ return true;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getEntityIDPostfix()
+ */
+ @Override
+ public String getEntityID() {
+ return authUrl + IdAustriaAuthConstants.ENDPOINT_METADATA;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getEntityFriendlyName()
+ */
+ @Override
+ public String getEntityFriendlyName() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getContactPersonInformation()
+ */
+ @Override
+ public List<ContactPerson> getContactPersonInformation() {
+ try {
+ return pvpConfiguration.getIdpContacts();
+
+ } catch (final EaafException e) {
+ log.warn("Can not load Metadata entry: Contect Person", e);
+ return null;
+
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getOrgansiationInformation()
+ */
+ @Override
+ public Organization getOrgansiationInformation() {
+ try {
+ return pvpConfiguration.getIdpOrganisation();
+
+ } catch (final EaafException e) {
+ log.warn("Can not load Metadata entry: Organisation", e);
+ return null;
+
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getMetadataSigningCredentials()
+ */
+ @Override
+ public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException {
+ return credentialProvider.getMetaDataSigningCredential();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getRequestorResponseSigningCredentials()
+ */
+ @Override
+ public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException {
+ return credentialProvider.getMessageSigningCredential();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getEncryptionCredentials()
+ */
+ @Override
+ public Credential getEncryptionCredentials() throws CredentialsNotAvailableException {
+ return credentialProvider.getMessageEncryptionCredential();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getIDPWebSSOPostBindingURL()
+ */
+ @Override
+ public String getIdpWebSsoPostBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getIDPWebSSORedirectBindingURL()
+ */
+ @Override
+ public String getIdpWebSsoRedirectBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getIDPSLOPostBindingURL()
+ */
+ @Override
+ public String getIdpSloPostBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getIDPSLORedirectBindingURL()
+ */
+ @Override
+ public String getIdpSloRedirectBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPAssertionConsumerServicePostBindingURL()
+ */
+ @Override
+ public String getSpAssertionConsumerServicePostBindingUrl() {
+ return authUrl + IdAustriaAuthConstants.ENDPOINT_POST;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPAssertionConsumerServiceRedirectBindingURL()
+ */
+ @Override
+ public String getSpAssertionConsumerServiceRedirectBindingUrl() {
+ return authUrl + IdAustriaAuthConstants.ENDPOINT_REDIRECT;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPSLOPostBindingURL()
+ */
+ @Override
+ public String getSpSloPostBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPSLORedirectBindingURL()
+ */
+ @Override
+ public String getSpSloRedirectBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPSLOSOAPBindingURL()
+ */
+ @Override
+ public String getSpSloSoapBindingUrl() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getIDPPossibleAttributes()
+ */
+ @Override
+ public List<Attribute> getIdpPossibleAttributes() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getIDPPossibleNameITTypes()
+ */
+ @Override
+ public List<String> getIdpPossibleNameIdTypes() {
+ return null;
+ }
+
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPRequiredAttributes()
+ */
+ @Override
+ public Collection<RequestedAttribute> getSpRequiredAttributes() {
+ final Map<String, RequestedAttribute> requestedAttributes = new HashMap<>();
+ log.trace("Build required attributes for ID Austria operaton ... ");
+ injectDefinedAttributes(requestedAttributes,
+ IdAustriaAuthConstants.DEFAULT_REQUIRED_PVP_ATTRIBUTES);
+
+
+ if (additionalAttributes != null) {
+ log.trace("Add additional PVP attributes into metadata ... ");
+ for (final RequestedAttribute el : additionalAttributes) {
+ if (requestedAttributes.containsKey(el.getName())) {
+ log.debug("Attribute " + el.getName()
+ + " is already added by default configuration. Overwrite it by user configuration");
+ }
+
+ requestedAttributes.put(el.getName(), el);
+
+ }
+ }
+
+ return requestedAttributes.values();
+
+ }
+
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#
+ * getSPAllowedNameITTypes()
+ */
+ @Override
+ public List<String> getSpAllowedNameIdTypes() {
+ return Arrays.asList(NameIDType.PERSISTENT);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPMetadataBuilderConfiguration#getSPNameForLogging()
+ */
+ @Override
+ public String getSpNameForLogging() {
+ return IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPMetadataBuilderConfiguration#wantAssertionSigned()
+ */
+ @Override
+ public boolean wantAssertionSigned() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPMetadataBuilderConfiguration#wantAuthnRequestSigned()
+ */
+ @Override
+ public boolean wantAuthnRequestSigned() {
+ return true;
+ }
+
+ /**
+ * Add additonal PVP attributes that are required by this deployment.
+ *
+ * @param additionalAttr List of PVP attribute name and isRequired flag
+ */
+ public void setAdditionalRequiredAttributes(List<Pair<String, Boolean>> additionalAttr) {
+ if (additionalAttr != null && !additionalAttr.isEmpty()) {
+ additionalAttributes = new ArrayList<>();
+ for (final Pair<String, Boolean> el : additionalAttr) {
+ final Attribute attributBuilder = PvpAttributeBuilder.buildEmptyAttribute(el.getFirst());
+ if (attributBuilder != null) {
+ additionalAttributes.add(
+ PvpAttributeBuilder.buildReqAttribute(
+ attributBuilder.getName(),
+ attributBuilder.getFriendlyName(),
+ el.getSecond()));
+
+ } else {
+ log.info("NO PVP attribute with name: " + el.getFirst());
+ }
+
+ }
+ }
+ }
+
+ private void injectDefinedAttributes(Map<String, RequestedAttribute> requestedAttributes,
+ List<Triple<String, String, Boolean>> attributes) {
+ for (final Triple<String, String, Boolean> el : attributes) {
+ requestedAttributes.put(el.getFirst(), PvpAttributeBuilder.buildReqAttribute(el.getFirst(), el
+ .getSecond(), el.getThird()));
+
+ }
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthRequestBuilderConfiguration.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthRequestBuilderConfiguration.java
new file mode 100644
index 00000000..52bd1c5f
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthRequestBuilderConfiguration.java
@@ -0,0 +1,307 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.config;
+
+import java.util.List;
+
+import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.w3c.dom.Element;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+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.sp.api.IPvpAuthnRequestBuilderConfiguruation;
+
+/**
+ * ID Austria client-specific implementation of an {@link IPvpAuthnRequestBuilderConfiguruation}.
+ *
+ * @author tlenz
+ *
+ */
+public class IdAustriaAuthRequestBuilderConfiguration implements IPvpAuthnRequestBuilderConfiguruation {
+
+ private boolean isPassive;
+ private String spEntityId;
+ private String qaaLevel;
+ private EntityDescriptor idpEntity;
+ private EaafX509Credential signCred;
+ private String scopeRequesterId;
+ private String providerName;
+ private List<EaafRequestedAttribute> requestedAttributes;
+ private String reqId;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#isPassivRequest()
+ */
+ @Override
+ public Boolean isPassivRequest() {
+ return this.isPassive;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getAssertionConsumerServiceId()
+ */
+ @Override
+ public Integer getAssertionConsumerServiceId() {
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getEntityID()
+ */
+ @Override
+ public String getSpEntityID() {
+ return this.spEntityId;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getNameIDPolicy()
+ */
+ @Override
+ public String getNameIdPolicyFormat() {
+ return NameIDType.PERSISTENT;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getNameIDPolicy()
+ */
+ @Override
+ public boolean getNameIdPolicyAllowCreation() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getAuthnContextClassRef()
+ */
+ @Override
+ public String getAuthnContextClassRef() {
+ return this.qaaLevel;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getAuthnContextComparison()
+ */
+ @Override
+ public AuthnContextComparisonTypeEnumeration getAuthnContextComparison() {
+ return AuthnContextComparisonTypeEnumeration.MINIMUM;
+ }
+
+ /**
+ * Set isPassive flag in SAML2 request.
+ *
+ * @param isPassive the isPassive to set.
+ */
+ public void setPassive(boolean isPassive) {
+ this.isPassive = isPassive;
+ }
+
+ /**
+ * Set the requester EntityId.
+ *
+ * @param spEntityId EntityId of SP
+ */
+ public void setSpEntityID(String spEntityId) {
+ this.spEntityId = spEntityId;
+ }
+
+ /**
+ * Set required LoA.
+ *
+ * @param loa the LoA to set.
+ */
+ public void setRequestedLoA(String loa) {
+ qaaLevel = loa;
+ }
+
+ /**
+ * Set EntityId of IDP.
+ *
+ * @param idpEntity the idpEntity to set.
+ */
+ public void setIdpEntity(EntityDescriptor idpEntity) {
+ this.idpEntity = idpEntity;
+ }
+
+ /**
+ * Set message signing credentials.
+ *
+ * @param signCred the signCred to set.
+ */
+ public void setSignCred(EaafX509Credential signCred) {
+ this.signCred = signCred;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getAuthnRequestSigningCredential()
+ */
+ @Override
+ public EaafX509Credential getAuthnRequestSigningCredential() {
+ return this.signCred;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getIDPEntityDescriptor()
+ */
+ @Override
+ public EntityDescriptor getIdpEntityDescriptor() {
+ return this.idpEntity;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getSubjectNameID()
+ */
+ @Override
+ public String getSubjectNameID() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getSPNameForLogging()
+ */
+ @Override
+ public String getSpNameForLogging() {
+ return IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getSubjectNameIDFormat()
+ */
+ @Override
+ public String getSubjectNameIdFormat() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getRequestID()
+ */
+ @Override
+ public String getRequestID() {
+ return this.reqId;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getSubjectNameIDQualifier()
+ */
+ @Override
+ public String getSubjectNameIdQualifier() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getSubjectConformationMethode()
+ */
+ @Override
+ public String getSubjectConformationMethode() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.
+ * IPVPAuthnRequestBuilderConfiguruation#getSubjectConformationDate()
+ */
+ @Override
+ public Element getSubjectConformationDate() {
+ return null;
+ }
+
+ @Override
+ public List<EaafRequestedAttribute> getRequestedAttributes() {
+ return this.requestedAttributes;
+
+ }
+
+ @Override
+ public String getProviderName() {
+ return this.providerName;
+ }
+
+ @Override
+ public String getScopeRequesterId() {
+ return this.scopeRequesterId;
+ }
+
+ /**
+ * Set the entityId of the SP that requests the proxy for eIDAS authentication.
+ *
+ * @param scopeRequesterId RequestId in SAML2 Proxy extension
+ */
+ public void setScopeRequesterId(String scopeRequesterId) {
+ this.scopeRequesterId = scopeRequesterId;
+ }
+
+ /**
+ * Set a friendlyName for the SP that requests the proxy for eIDAS
+ * authentication.
+ *
+ * @param providerName SAML2 provider-name attribute-value
+ */
+ public void setProviderName(String providerName) {
+ this.providerName = providerName;
+ }
+
+ /**
+ * Set a Set of PVP attributes that a requested by using requested attributes.
+ *
+ * @param requestedAttributes Requested SAML2 attributes
+ */
+ public void setRequestedAttributes(List<EaafRequestedAttribute> requestedAttributes) {
+ this.requestedAttributes = requestedAttributes;
+ }
+
+ /**
+ * Set a RequestId for this Authn. Request.
+ *
+ * @param reqId SAML2 message requestId
+ */
+ public void setRequestId(String reqId) {
+ this.reqId = reqId;
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthMetadataController.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthMetadataController.java
new file mode 100644
index 00000000..ad708d30
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthMetadataController.java
@@ -0,0 +1,150 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.controller;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.google.common.net.MediaType;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.config.IdAustriaAuthMetadataConfiguration;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.http.HttpUtils;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Controller that generates SAML2 metadata for ID Austria authentication client.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+@Controller
+public class IdAustriaAuthMetadataController extends AbstractController {
+
+ private static final String ERROR_CODE_INTERNAL_00 = "eaaf.core.00";
+
+ @Autowired
+ PvpMetadataBuilder metadatabuilder;
+ @Autowired
+ IdAustriaAuthCredentialProvider credentialProvider;
+ @Autowired
+ IPvp2BasicConfiguration pvpConfiguration;
+
+ /**
+ * Default construction with logging.
+ *
+ */
+ public IdAustriaAuthMetadataController() {
+ super();
+ log.debug("Registering servlet " + getClass().getName()
+ + " with mappings '" + IdAustriaAuthConstants.ENDPOINT_METADATA
+ + "'.");
+
+ }
+
+ /**
+ * End-point that produce PVP2 metadata for ID Austria authentication client.
+ *
+ * @param req http Request
+ * @param resp http Response
+ * @throws IOException In case of an I/O error
+ * @throws EaafException In case of a metadata generation error
+ */
+ @RequestMapping(value = IdAustriaAuthConstants.ENDPOINT_METADATA,
+ method = { RequestMethod.GET })
+ public void getSpMetadata(HttpServletRequest req, HttpServletResponse resp) throws IOException,
+ EaafException {
+ // check PublicURL prefix
+ try {
+ final String authUrl = getAuthUrlFromHttpContext(req);
+
+ // initialize metadata builder configuration
+ final IdAustriaAuthMetadataConfiguration metadataConfig =
+ new IdAustriaAuthMetadataConfiguration(authUrl, credentialProvider, pvpConfiguration);
+ metadataConfig.setAdditionalRequiredAttributes(getAdditonalRequiredAttributes());
+
+ // build metadata
+ final String xmlMetadata = metadatabuilder.buildPvpMetadata(metadataConfig);
+
+ // write response
+ final byte[] content = xmlMetadata.getBytes("UTF-8");
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.setContentLength(content.length);
+ resp.setContentType(MediaType.XML_UTF_8.toString());
+ resp.getOutputStream().write(content);
+
+ } catch (final Exception e) {
+ log.warn("Build PVP metadata for ID Austria client FAILED.", e);
+ protAuthService.handleErrorNoRedirect(e, req, resp, false);
+
+ }
+
+ }
+
+ private String getAuthUrlFromHttpContext(HttpServletRequest req) throws EaafException {
+ // check if End-Point is valid
+ final String authUrlString = HttpUtils.extractAuthUrlFromRequest(req);
+ URL authReqUrl;
+ try {
+ authReqUrl = new URL(authUrlString);
+
+ } catch (final MalformedURLException e) {
+ log.warn("Requested URL: {} is not a valid URL.", authUrlString);
+ throw new EaafAuthenticationException(ERROR_CODE_INTERNAL_00, new Object[] { authUrlString }, e);
+
+ }
+
+ final String idpAuthUrl = authConfig.validateIdpUrl(authReqUrl);
+ if (idpAuthUrl == null) {
+ log.warn("Requested URL: {} is NOT found in configuration.", authReqUrl);
+ throw new EaafAuthenticationException(ERROR_CODE_INTERNAL_00, new Object[] { authUrlString });
+
+ }
+
+ return idpAuthUrl;
+ }
+
+ private List<Pair<String, Boolean>> getAdditonalRequiredAttributes() {
+ final List<Pair<String, Boolean>> result = new ArrayList<>();
+ // load attributes from configuration
+ final Map<String, String> addReqAttributes = authConfig.getBasicConfigurationWithPrefix(
+ IdAustriaAuthConstants.CONFIG_PROPS_REQUIRED_PVP_ATTRIBUTES_LIST);
+ for (final String el : addReqAttributes.values()) {
+ if (StringUtils.isNotEmpty(el)) {
+ log.trace("Parse additional attr. definition: " + el);
+ final List<String> attr = KeyValueUtils.getListOfCsvValues(el.trim());
+ if (attr.size() == 2) {
+ result.add(Pair.newInstance(attr.get(0), Boolean.parseBoolean(attr.get(1))));
+
+ } else {
+ log.info("IGNORE additional attr. definition: " + el
+ + " Reason: Format not valid");
+ }
+ }
+ }
+
+ return result;
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthSignalController.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthSignalController.java
new file mode 100644
index 00000000..2e7868fd
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthSignalController.java
@@ -0,0 +1,94 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.controller;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringEscapeUtils;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractProcessEngineSignalController;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Controller that receives the response from ID Austria system.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+@Controller
+public class IdAustriaAuthSignalController extends AbstractProcessEngineSignalController {
+
+ public static final String HTTP_PARAM_RELAYSTATE = "RelayState";
+
+ /**
+ * Default constructor with logging.
+ *
+ */
+ public IdAustriaAuthSignalController() {
+ super();
+ log.debug("Registering servlet " + getClass().getName()
+ + " with mappings '" + IdAustriaAuthConstants.ENDPOINT_POST
+ + "' and '" + IdAustriaAuthConstants.ENDPOINT_REDIRECT + "'.");
+
+ }
+
+ /**
+ * HTTP end-point for incoming SAML2 Respone from ID Austrian System.
+ *
+ * @param req HTTP request
+ * @param resp HTTP response
+ * @throws IOException In case of a HTTP communication error
+ * @throws EaafException In case of a state-validation problem
+ */
+ @RequestMapping(value = { IdAustriaAuthConstants.ENDPOINT_POST,
+ IdAustriaAuthConstants.ENDPOINT_REDIRECT },
+ method = { RequestMethod.POST, RequestMethod.GET })
+ public void performEidasAuthentication(HttpServletRequest req, HttpServletResponse resp)
+ throws IOException, EaafException {
+ signalProcessManagement(req, resp);
+
+ }
+
+ /**
+ * Read the PendingRequestId from SAML2 RelayState parameter.
+ */
+ @Override
+ public String getPendingRequestId(HttpServletRequest request) {
+ String relayState = StringEscapeUtils.escapeHtml4(request.getParameter(HTTP_PARAM_RELAYSTATE));
+ if (StringUtils.isNotEmpty(relayState)) {
+ try {
+ String pendingReqId = transactionStorage.get(relayState, String.class);
+ if (StringUtils.isNotEmpty(pendingReqId)) {
+
+ return pendingReqId;
+
+ } else {
+ log.info("SAML2 RelayState from request is unknown. Can NOT restore session ... ");
+
+ }
+
+ } catch (EaafException e) {
+ log.error("Can NOT map SAML2 RelayState to pendingRequestId", e);
+
+ } finally {
+ transactionStorage.remove(relayState);
+
+ }
+
+ } else {
+ log.info("No SAML2 relaystate. Can NOT restore session ... ");
+
+ }
+
+ return null;
+
+ }
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java
new file mode 100644
index 00000000..e486b851
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java
@@ -0,0 +1,393 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.tasks;
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.naming.ConfigurationException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.Utils;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+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.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+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.binding.PostBinding;
+import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage;
+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.EaafUriCompare;
+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.sp.exception.AssertionValidationExeption;
+import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnResponseValidationException;
+import at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils.AssertionAttributeExtractor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * ID Austria authentication task that receives the SAML2 response from ID
+ * Austria system.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class ReceiveFromIdAustriaSystemTask extends AbstractAuthServletTask {
+
+ private static final String ERROR_PVP_03 = "sp.pvp2.03";
+ private static final String ERROR_PVP_05 = "sp.pvp2.05";
+ private static final String ERROR_PVP_06 = "sp.pvp2.06";
+ private static final String ERROR_PVP_08 = "sp.pvp2.08";
+ private static final String ERROR_PVP_10 = "sp.pvp2.10";
+ private static final String ERROR_PVP_11 = "sp.pvp2.11";
+ private static final String ERROR_PVP_12 = "sp.pvp2.12";
+
+ private static final String ERROR_MSG_00 =
+ "Receive INVALID PVP Response from federated IDP";
+ private static final String ERROR_MSG_01 =
+ "Processing PVP response from 'ms-specific eIDAS node' FAILED.";
+ private static final String ERROR_MSG_02 =
+ "PVP response decrytion FAILED. No credential found.";
+ private static final String ERROR_MSG_03 =
+ "PVP response validation FAILED.";
+
+ @Autowired
+ private SamlVerificationEngine samlVerificationEngine;
+ @Autowired
+ private IdAustriaAuthCredentialProvider credentialProvider;
+ @Autowired(required = true)
+ IdAustriaAuthMetadataProvider metadataProvider;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask#execute(at.gv.
+ * egovernment.moa.id.process.api.ExecutionContext,
+ * javax.servlet.http.HttpServletRequest,
+ * javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response)
+ throws TaskExecutionException {
+ InboundMessage msg = null;
+
+ try {
+
+ IDecoder decoder = null;
+ EaafUriCompare comperator = null;
+ // select Response Binding
+ if (request.getMethod().equalsIgnoreCase("POST")) {
+ decoder = new PostBinding();
+ comperator = new EaafUriCompare(pendingReq.getAuthUrl() + IdAustriaAuthConstants.ENDPOINT_POST);
+ log.trace("Receive PVP Response from 'ID Austria', by using POST-Binding.");
+
+ } else if (request.getMethod().equalsIgnoreCase("GET")) {
+ decoder = new RedirectBinding();
+ comperator = new EaafUriCompare(pendingReq.getAuthUrl()
+ + IdAustriaAuthConstants.ENDPOINT_REDIRECT);
+ log.trace("Receive PVP Response from 'ID Austria', by using Redirect-Binding.");
+
+ } else {
+ log.warn("Receive PVP Response, but Binding ("
+ + request.getMethod() + ") is not supported.");
+ throw new AuthnResponseValidationException(ERROR_PVP_03, new Object[] {
+ IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING });
+
+ }
+
+ // decode PVP response object
+ msg = (InboundMessage) decoder.decode(
+ request, response, metadataProvider, IDPSSODescriptor.DEFAULT_ELEMENT_NAME,
+ comperator);
+
+ // validate response signature
+ if (!msg.isVerified()) {
+ samlVerificationEngine.verify(msg,
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+ msg.setVerified(true);
+
+ }
+
+ // validate assertion
+ final Pair<PvpSProfileResponse, Boolean> processedMsg =
+ preProcessAuthResponse((PvpSProfileResponse) msg);
+
+ // check if SAML2 response contains user-stop decision
+ if (processedMsg.getSecond()) {
+ stopProcessFromUserDecision(executionContext, request, response);
+
+ } else {
+ // validate entityId of response
+ final String idAustriaEntityID =
+ Utils.getIdAustriaEntityId(pendingReq.getServiceProviderConfiguration(), authConfig);
+ final String respEntityId = msg.getEntityID();
+ if (!idAustriaEntityID.equals(respEntityId)) {
+ log.warn("Response Issuer is not a 'ID Austria System'. Stopping eIDAS authentication ...");
+ throw new AuthnResponseValidationException(ERROR_PVP_08,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING,
+ msg.getEntityID() });
+
+ }
+
+ // initialize Attribute extractor
+ final AssertionAttributeExtractor extractor =
+ new AssertionAttributeExtractor(processedMsg.getFirst().getResponse());
+
+ getAuthDataFromInterfederation(extractor);
+
+ // set NeedConsent to false, because user gives consont during authentication
+ pendingReq.setNeedUserConsent(false);
+
+ // store pending-request
+ requestStoreage.storePendingRequest(pendingReq);
+
+ // write log entries
+ // revisionsLogger.logEvent(pendingReq,
+ // EidasAuthEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_MDS_VALID);
+ log.info("Receive a valid assertion from IDP " + msg.getEntityID());
+
+ }
+
+ } catch (final AuthnResponseValidationException e) {
+ throw new TaskExecutionException(pendingReq, ERROR_MSG_03, e);
+
+ } catch (MessageDecodingException | SecurityException | SamlSigningException e) {
+ final String samlRequest = request.getParameter("SAMLRequest");
+ log.debug("Receive INVALID PVP Response from 'ID Austria System': {}",
+ samlRequest, null, e);
+ throw new TaskExecutionException(pendingReq, ERROR_MSG_00,
+ new AuthnResponseValidationException(ERROR_PVP_11,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING }, e));
+
+ } catch (IOException | MarshallingException | TransformerException e) {
+ log.debug("Processing PVP response from 'ID Austria System' FAILED.", e);
+ throw new TaskExecutionException(pendingReq, ERROR_MSG_01,
+ new AuthnResponseValidationException(ERROR_PVP_12,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING, e.getMessage() },
+ e));
+
+ } catch (final CredentialsNotAvailableException e) {
+ log.debug("PVP response decrytion FAILED. No credential found.", e);
+ throw new TaskExecutionException(pendingReq, ERROR_MSG_02,
+ new AuthnResponseValidationException(ERROR_PVP_10,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING }, e));
+
+ } catch (final Exception e) {
+ log.debug("PVP response validation FAILED. Msg:" + e.getMessage(), e);
+ throw new TaskExecutionException(pendingReq, ERROR_MSG_03,
+ new AuthnResponseValidationException(ERROR_PVP_12,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING, e.getMessage() }, e));
+
+ }
+
+ }
+
+ private void getAuthDataFromInterfederation(AssertionAttributeExtractor extractor)
+ throws EaafBuilderException, ConfigurationException {
+
+ final Set<String> requiredEidasNodeAttributes =
+ IdAustriaAuthConstants.DEFAULT_REQUIRED_PVP_ATTRIBUTE_NAMES;
+ try {
+ // check if all attributes are include
+ if (!extractor.containsAllRequiredAttributes()
+ || !extractor.containsAllRequiredAttributes(
+ requiredEidasNodeAttributes)) {
+ log.warn("PVP Response from 'ID Austria System' contains not all requested attributes.");
+ throw new AssertionValidationExeption(ERROR_PVP_06, new Object[] {
+ IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING });
+
+ }
+
+ // copy attributes into MOASession
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(
+ AuthProcessDataWrapper.class);
+
+ // validate response attributes
+ validateResponseAttributes(extractor);
+
+ // inject all attributes into session
+ final Set<String> includedAttrNames = extractor.getAllIncludeAttributeNames();
+ for (final String attrName : includedAttrNames) {
+ injectAuthInfosIntoSession(session, attrName,
+ extractor.getSingleAttributeValue(attrName));
+
+ }
+
+ // set foreigner flag
+ session.setForeigner(false);
+
+ // mark it as ID Austria process, because we have no baseId
+ session.setEidProcess(true);
+
+ // set IssuerInstant from Assertion
+ session.setIssueInstant(extractor.getAssertionIssuingDate());
+
+ // set mandate flag
+ session.setUseMandates(checkIfMandateInformationIsAvailable(extractor));
+
+
+ } catch (final EaafException | IOException e) {
+ throw new EaafBuilderException(ERROR_PVP_06, null, e.getMessage(), e);
+
+ }
+ }
+
+
+ /**
+ * Check if mandate information is available.
+ *
+ * @param extractor Assertion from ID Austria system.
+ * @return <code>true</code> if mandate was used, otherwise <code>false</code>
+ */
+ private boolean checkIfMandateInformationIsAvailable(AssertionAttributeExtractor extractor) {
+ boolean isMandateIncluded = extractor.containsAttribute(PvpAttributeDefinitions.MANDATE_TYPE_NAME);
+ log.debug("Response from ID-Austria system contains mandate information. Switch to mandate-mode ... ");
+ return isMandateIncluded;
+
+ }
+
+ private void validateResponseAttributes(AssertionAttributeExtractor extractor)
+ throws EaafAuthenticationException {
+ final String bpkTarget = extractor.getSingleAttributeValue(
+ PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME);
+ final String spTarget = pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier();
+ if (StringUtils.isNotEmpty(bpkTarget) && bpkTarget.equals(spTarget)) {
+ log.debug("Find attr: {} that matches to requested bPK target. bPK should be valid",
+ PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME);
+
+ } else {
+ log.trace("Find not attr: {}. Validation bPK attribute ... ",
+ PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME);
+ final String bpk = extractor.getSingleAttributeValue(PvpAttributeDefinitions.BPK_NAME);
+ final String[] split = bpk.split(":", 2);
+ if (split.length == 2) {
+ if (!spTarget.endsWith(split[0])) {
+ log.error("bPK from response: {} does not match to SP target: {}", bpk, spTarget);
+ throw new EaafAuthenticationException(IdAustriaAuthConstants.ERRORTYPE_06, null);
+
+ } else {
+ log.trace("Prefix of PVP bPK attribte matches to SP configuration. bPK looks valid");
+
+ }
+
+ } else {
+ log.warn("Find suspect bPK that has no prefix. Use it as it is ... ");
+
+ }
+ }
+ }
+
+ private void injectAuthInfosIntoSession(AuthProcessDataWrapper session,
+ String attrName, String attrValue) throws EaafStorageException, IOException {
+ log.trace("Inject attribute: {} with value: {} into AuthSession", attrName, attrValue);
+ log.debug("Inject attribute: {} into AuthSession", attrName);
+ if (PvpAttributeDefinitions.BPK_NAME.equals(attrName)) {
+ log.trace("Find bPK attribute. Extract eIDAS identifier ... ");
+ session.setGenericDataToSession(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ extractBpkFromResponse(attrValue));
+
+ } else {
+ session.setGenericDataToSession(attrName, attrValue);
+
+ }
+
+ }
+
+ private String extractBpkFromResponse(String pvpBpkAttrValue) {
+ final String[] split = pvpBpkAttrValue.split(":", 2);
+ if (split.length == 2) {
+ return split[1];
+
+ } else {
+ log.warn("PVP bPK attribute: {} has wrong format. Use it as it is.", pvpBpkAttrValue);
+ return pvpBpkAttrValue;
+
+ }
+ }
+
+ private Pair<PvpSProfileResponse, Boolean> preProcessAuthResponse(PvpSProfileResponse msg)
+ throws IOException, MarshallingException, TransformerException,
+ CredentialsNotAvailableException, AuthnResponseValidationException, SamlAssertionValidationExeption {
+ log.debug("Start PVP-2x assertion processing... ");
+ final Response samlResp = (Response) msg.getResponse();
+
+ // check SAML2 response status-code
+ if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS)) {
+ // validate PVP 2.1 assertion
+ samlVerificationEngine.validateAssertion(samlResp,
+ credentialProvider.getMessageEncryptionCredential(),
+ pendingReq.getAuthUrl() + IdAustriaAuthConstants.ENDPOINT_METADATA,
+ IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING);
+
+ msg.setSamlMessage(Saml2Utils.asDomDocument(samlResp).getDocumentElement());
+ // revisionsLogger.logEvent(pendingReq,
+ // EidasAuthEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_RECEIVED,
+ // samlResp.getID());
+ return Pair.newInstance(msg, false);
+
+ } else {
+ log.info("Receive StatusCode " + samlResp.getStatus().getStatusCode().getValue()
+ + " from 'ms-specific eIDAS node'.");
+ final StatusCode subStatusCode = getSubStatusCode(samlResp);
+ if (subStatusCode != null
+ && IdAustriaAuthConstants.SAML2_STATUSCODE_USERSTOP.equals(subStatusCode.getValue())) {
+ log.info("Find 'User-Stop operation' in SAML2 response. Stopping authentication process ... ");
+ return Pair.newInstance(msg, true);
+
+ }
+
+ // revisionsLogger.logEvent(pendingReq,
+ // EidasAuthEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_RECEIVED_ERROR);
+ throw new AuthnResponseValidationException(ERROR_PVP_05,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING,
+ samlResp.getIssuer().getValue(),
+ samlResp.getStatus().getStatusCode().getValue(),
+ samlResp.getStatus().getStatusMessage().getValue() });
+
+ }
+
+ }
+
+ /**
+ * Get SAML2 Sub-StatusCode if not <code>null</code>.
+ *
+ * @param samlResp SAML2 response
+ * @return Sub-StatusCode or <code>null</code> if it's not set
+ */
+ private StatusCode getSubStatusCode(Response samlResp) {
+ if (samlResp.getStatus().getStatusCode().getStatusCode() != null
+ && StringUtils.isNotEmpty(samlResp.getStatus().getStatusCode().getStatusCode().getValue())) {
+ return samlResp.getStatus().getStatusCode().getStatusCode();
+
+ }
+ return null;
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java
new file mode 100644
index 00000000..66aadde6
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java
@@ -0,0 +1,205 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.tasks;
+
+import java.security.NoSuchAlgorithmException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.saml.saml2.core.Attribute;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.config.IdAustriaAuthRequestBuilderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.Utils;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+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.Random;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder;
+import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils;
+import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException;
+import at.gv.egiz.eaaf.modules.pvp2.sp.impl.PvpAuthnRequestBuilder;
+import lombok.extern.slf4j.Slf4j;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+import net.shibboleth.utilities.java.support.security.impl.SecureRandomIdentifierGenerationStrategy;
+
+/**
+ * eIDAS Authentication task that generates PVP2 S-Profile request to central
+ * Austrian MS-Connector.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class RequestIdAustriaSystemTask extends AbstractAuthServletTask {
+
+ private static final String ERROR_PVP_02 = "sp.pvp2.02";
+ private static final String ERROR_PVP_13 = "sp.pvp2.13";
+
+ private static final String ERROR_MSG_1 =
+ "Requested 'ms-specific eIDAS node' {0} has no valid metadata or metadata is not found";
+ private static final String ERROR_MSG_4 =
+ "Build PVP2.1 AuthnRequest to connect 'ms-specific eIDAS node' FAILED.";
+
+ @Autowired PvpAuthnRequestBuilder authnReqBuilder;
+ @Autowired IdAustriaAuthCredentialProvider credential;
+ @Autowired IdAustriaAuthMetadataProvider metadataService;
+ @Autowired ITransactionStorage transactionStorage;
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response)
+ throws TaskExecutionException {
+ try {
+ //revisionsLogger.logEvent(pendingReq, EidasAuthEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_SELECTED);
+
+ // get entityID for central ID Austria system
+ final String idAustriaEntityID =
+ Utils.getIdAustriaEntityId(pendingReq.getServiceProviderConfiguration(), authConfig);
+ if (StringUtils.isEmpty(idAustriaEntityID)) {
+ log.info("ID Austria authentication not possible -> NO EntityID for central central ID Austria System FOUND!");
+ throw new EaafConfigurationException(IdAustriaAuthConstants.ERRORTYPE_00,
+ new Object[] { IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID });
+
+ }
+
+ // load IDP SAML2 entitydescriptor
+ final EntityDescriptor entityDesc = metadataService.getEntityDescriptor(idAustriaEntityID);
+ if (entityDesc == null) {
+ throw new EaafConfigurationException(IdAustriaAuthConstants.ERRORTYPE_05,
+ new Object[] { MessageFormat.format(ERROR_MSG_1, idAustriaEntityID) });
+
+ }
+
+ // setup AuthnRequestBuilder configuration
+ final IdAustriaAuthRequestBuilderConfiguration authnReqConfig =
+ new IdAustriaAuthRequestBuilderConfiguration();
+ final SecureRandomIdentifierGenerationStrategy gen =
+ new SecureRandomIdentifierGenerationStrategy();
+
+ // set basic infos
+ authnReqConfig.setRequestId(gen.generateIdentifier());
+ authnReqConfig.setIdpEntity(entityDesc);
+ authnReqConfig.setPassive(false);
+ authnReqConfig.setSignCred(credential.getMessageSigningCredential());
+ authnReqConfig.setSpEntityID(pendingReq.getAuthUrl() + IdAustriaAuthConstants.ENDPOINT_METADATA);
+
+ // set eIDAS Proxy-Service specific information for ID Austria system
+ authnReqConfig.setRequestedAttributes(buildRequestedAttributes(pendingReq));
+
+
+ /*build relayState for session synchronization, because SAML2 only allows RelayState with 80 characters
+ * but encrypted PendingRequestId is much longer.
+ */
+ String relayState = Random.nextProcessReferenceValue();
+ transactionStorage.put(relayState, pendingReq.getPendingRequestId(), -1);
+
+ // build and transmit AuthnRequest
+ authnReqBuilder.buildAuthnRequest(pendingReq, authnReqConfig, relayState, response);
+
+ //revisionsLogger.logEvent(pendingReq,
+ // EidasAuthEventConstants.AUTHPROCESS_EIDAS_AT_CONNECTOR_REQUESTED,
+ // authnReqConfig.getRequestID());
+
+ } catch (final EaafException e) {
+ throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+
+ } catch (final ResolverException e) {
+ throw new TaskExecutionException(pendingReq,
+ ERROR_MSG_4,
+ new AuthnRequestBuildException(ERROR_PVP_02,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING }, e));
+
+ } catch (MessageEncodingException | NoSuchAlgorithmException | SecurityException e) {
+ throw new TaskExecutionException(pendingReq,
+ e.getMessage(),
+ new AuthnRequestBuildException(ERROR_PVP_13,
+ new Object[] { IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING }, e));
+
+ } catch (final Exception e) {
+ throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+
+ }
+ }
+
+ private String selectHighestLoa(List<String> requiredLoA) {
+ //TODO: implement LoA selection
+ return requiredLoA.get(0);
+
+ }
+
+ private List<EaafRequestedAttribute> buildRequestedAttributes(IRequest pendingReq) {
+ final List<EaafRequestedAttribute> attributs = new ArrayList<>();
+
+ //build attribute that contains the unique identifier of the eIDAS-Connector
+ injectAttribute(attributs, ExtendedPvpAttributeDefinitions.EIDAS_CONNECTOR_UNIQUEID_NAME,
+ pendingReq.getServiceProviderConfiguration().getUniqueIdentifier());
+
+ // build EID sector for identification attribute
+ injectAttribute(attributs, PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME,
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier());
+
+ // set requested LoA as attribute
+ injectAttribute(attributs, PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME,
+ selectHighestLoa(pendingReq.getServiceProviderConfiguration().getRequiredLoA()));
+
+ //set ProviderName if available
+ String providerName = ((ProxyServicePendingRequest)pendingReq).getEidasRequest().getProviderName();
+ if (StringUtils.isNotEmpty(providerName)) {
+ injectAttribute(attributs, ExtendedPvpAttributeDefinitions.SP_FRIENDLYNAME_NAME, providerName);
+
+ }
+
+ //set ProviderName if available
+ String requesterId = ((ProxyServicePendingRequest)pendingReq).getEidasRequest().getRequesterId();
+ if (StringUtils.isNotEmpty(requesterId)) {
+ injectAttribute(attributs, ExtendedPvpAttributeDefinitions.SP_UNIQUEID_NAME, requesterId);
+
+ }
+
+ //set mandate profiles
+ List<String> mandateProfiles =
+ pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).getMandateProfiles();
+ if (mandateProfiles != null && !mandateProfiles.isEmpty()) {
+ log.debug("Set mandate-profiles attribute into ID-Austria request");
+ injectAttribute(attributs, ExtendedPvpAttributeDefinitions.SP_USED_MANDATE_PROFILES_NAME,
+ StringUtils.join(mandateProfiles, ","));
+
+ }
+
+ // inject mandate mode attribute
+ injectAttribute(attributs, ExtendedPvpAttributeDefinitions.SP_USED_MANDATE_TYPE_NAME,
+ pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).getMandateMode().getMode());
+
+
+ return attributs;
+ }
+
+ private void injectAttribute(List<EaafRequestedAttribute> attributs, String attributeName, String attributeValue) {
+ final Attribute requesterIdAttr = PvpAttributeBuilder.buildEmptyAttribute(attributeName);
+ final EaafRequestedAttribute requesterIdReqAttr = Saml2Utils.generateReqAuthnAttributeSimple(
+ requesterIdAttr,
+ true,
+ attributeValue);
+ attributs.add(requesterIdReqAttr);
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthCredentialProvider.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthCredentialProvider.java
new file mode 100644
index 00000000..7da306b5
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthCredentialProvider.java
@@ -0,0 +1,130 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.utils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+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;
+
+/**
+ * Credential provider for ID Austria PVP S-Profile client.
+ *
+ * @author tlenz
+ *
+ */
+public class IdAustriaAuthCredentialProvider extends AbstractCredentialProvider {
+
+ @Autowired
+ IConfiguration authConfig;
+
+
+ @Override
+ public KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException {
+ final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration();
+ keyStoreConfig.setFriendlyName(IdAustriaAuthConstants.MODULE_NAME_FOR_LOGGING);
+ keyStoreConfig.setKeyStoreType(
+ authConfig.getBasicConfiguration(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_TYPE,
+ KeyStoreType.PKCS12.getKeyStoreType()));
+ keyStoreConfig.setKeyStoreName(
+ authConfig.getBasicConfiguration(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_NAME));
+ keyStoreConfig.setSoftKeyStoreFilePath(getKeyStoreFilePath());
+ keyStoreConfig.setSoftKeyStorePassword(
+ authConfig.getBasicConfiguration(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTOREPASSWORD));
+
+ return keyStoreConfig;
+
+ }
+
+ private String getKeyStoreFilePath() throws EaafConfigurationException {
+ final String path = authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_PATH);
+ if (path == null) {
+ throw new EaafConfigurationException(IdAustriaAuthConstants.ERRORTYPE_00,
+ new Object[] { IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_PATH });
+
+ }
+ return path;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#
+ * getMetadataKeyAlias()
+ */
+ @Override
+ public String getMetadataKeyAlias() {
+ return authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_ALIAS);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#
+ * getMetadataKeyPassword()
+ */
+ @Override
+ public String getMetadataKeyPassword() {
+ return authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_PASSWORD);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#
+ * getSignatureKeyAlias()
+ */
+ @Override
+ public String getSignatureKeyAlias() {
+ return authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#
+ * getSignatureKeyPassword()
+ */
+ @Override
+ public String getSignatureKeyPassword() {
+ return authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_PASSWORD);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#
+ * getEncryptionKeyAlias()
+ */
+ @Override
+ public String getEncryptionKeyAlias() {
+ return authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_ALIAS);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#
+ * getEncryptionKeyPassword()
+ */
+ @Override
+ public String getEncryptionKeyPassword() {
+ return authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD);
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthMetadataProvider.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthMetadataProvider.java
new file mode 100644
index 00000000..72c52488
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthMetadataProvider.java
@@ -0,0 +1,168 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.utils;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.cert.CertificateException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+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;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+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.credential.KeyStoreConfiguration.KeyStoreType;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.http.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 at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * SAML2 metadata-provider implementation for ID Austria client.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class IdAustriaAuthMetadataProvider extends AbstractChainingMetadataProvider {
+
+ private static final String FRIENDLYNAME_METADATA_TRUSTSTORE = "'ID Austria client-metadata truststore'";
+ private static final String PROVIDER_ID_PATTERN = "ID Austria resolver: {0}";
+ public static final String PROVIDER_ID = "ID Austria_client metadata provider'";
+
+ @Autowired
+ private IConfiguration basicConfig;
+
+ @Autowired
+ private PvpMetadataResolverFactory metadataProviderFactory;
+ @Autowired
+ private IHttpClientFactory httpClientFactory;
+
+ @Autowired
+ private EaafKeyStoreFactory keyStoreFactory;
+
+ private Pair<KeyStore, Provider> metadataSigningTrustStore;
+
+ @Override
+ protected String getMetadataUrl(String entityId) throws EaafConfigurationException {
+ log.trace("ID Austria uses SAML2 well-known location approach. EntityId is Metadata-URL");
+ return entityId;
+
+ }
+
+ @Override
+ protected MetadataResolver createNewMetadataProvider(String entityId) throws EaafConfigurationException,
+ IOException, CertificateException {
+ final List<MetadataFilter> filterList = new ArrayList<>();
+ filterList.add(new SchemaValidationFilter(true));
+ filterList.add(new SimpleMetadataSignatureVerificationFilter(
+ metadataSigningTrustStore.getFirst(), entityId));
+
+ final MetadataFilterChain filter = new MetadataFilterChain();
+ filter.setFilters(filterList);
+
+ try {
+ return metadataProviderFactory.createMetadataProvider(getMetadataUrl(entityId),
+ filter,
+ MessageFormat.format(PROVIDER_ID_PATTERN, entityId),
+ httpClientFactory.getHttpClient());
+
+ } catch (final Pvp2MetadataException e) {
+ log.info("Can NOT build metadata provider for entityId: {}", entityId);
+ throw new EaafConfigurationException(IdAustriaAuthConstants.ERRORTYPE_04,
+ new Object[] { entityId, e.getMessage() }, e);
+
+ }
+ }
+
+ @Override
+ protected List<String> getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException {
+ return Collections.emptyList();
+
+ }
+
+ @Override
+ protected String getMetadataProviderId() {
+ return PROVIDER_ID;
+
+ }
+
+ @Override
+ public void runGarbageCollector() {
+ log.trace("Garbage collection is NOT supported by: {}", getId());
+ }
+
+ @Override
+ public void doDestroy() {
+ super.fullyDestroy();
+
+ }
+
+ @PostConstruct
+ private void initialize() throws EaafException {
+ // initialize truststore to validate metadata signing certificates
+ initializeTrustStore();
+
+ // load metadata with metadataURL, as backup
+ initializeFileSystemMetadata();
+
+ }
+
+ private void initializeFileSystemMetadata() {
+ try {
+ final String metadataUrl = basicConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_METADATAURL);
+ if (StringUtils.isNotEmpty(metadataUrl)) {
+ log.info("Use not recommended metadata-provider initialization!"
+ + " SAML2 'Well-Known-Location' is the preferred methode.");
+ log.info("Initialize 'ID Austria' metadata-provider with URL: {}", metadataUrl);
+
+ addMetadataResolverIntoChain(createNewMetadataProvider(metadataUrl));
+ }
+
+ } catch (final EaafConfigurationException | CertificateException | IOException e) {
+ log.warn("Can NOT inject static eIDAS Node metadata-soure.", e);
+ log.warn("Communication with ID Austria can be FAIL.");
+
+ }
+ }
+
+ private void initializeTrustStore() throws EaafException {
+ // set configuration
+ final KeyStoreConfiguration trustStoreConfig = new KeyStoreConfiguration();
+ trustStoreConfig.setFriendlyName(FRIENDLYNAME_METADATA_TRUSTSTORE);
+ trustStoreConfig.setKeyStoreType(basicConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_TYPE,
+ KeyStoreType.JKS.getKeyStoreType()));
+ trustStoreConfig.setKeyStoreName(basicConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_NAME));
+ trustStoreConfig.setSoftKeyStoreFilePath(basicConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_PATH));
+ trustStoreConfig.setSoftKeyStorePassword(basicConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_PASSWORD));
+
+ // validate configuration
+ trustStoreConfig.validate();
+
+ // open new TrustStore
+ metadataSigningTrustStore = keyStoreFactory.buildNewKeyStore(trustStoreConfig);
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/Utils.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/Utils.java
new file mode 100644
index 00000000..1de6c33f
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/Utils.java
@@ -0,0 +1,44 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.utils;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+
+public class Utils {
+
+ /**
+ * Get the EntityId of the ID Austria system that
+ * should be used in this process.
+ *
+ * @param spConfiguration Service-Provider configuration that can include
+ * {@linkplain IdAustriaAuthConstants.CONFIG_PROPS_APPSPECIFIC_IDAUSTRIA_NODE_URL}
+ * @param authConfig Basic application configuration that include
+ * {@linkplain IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID}
+ * @return EntityId, or <code>null</code> if no EntityId was found in configuration
+ */
+ @Nullable
+ public static String getIdAustriaEntityId(
+ ISpConfiguration spConfiguration, IConfiguration authConfig) {
+ // load from service-provider configuration
+ String msNodeEntityID = spConfiguration.getConfigurationValue(
+ IdAustriaAuthConstants.CONFIG_PROPS_APPSPECIFIC_IDAUSTRIA_NODE_URL);
+
+ if (StringUtils.isEmpty(msNodeEntityID)) {
+ msNodeEntityID = authConfig.getBasicConfiguration(
+ IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID);
+
+ }
+
+ return msNodeEntityID;
+ }
+
+ private Utils() {
+ //hide constructor of private class
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
new file mode 100644
index 00000000..6bf41f6f
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -0,0 +1 @@
+at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthenticationSpringResourceProvider \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder b/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder
new file mode 100644
index 00000000..65e9482c
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder
@@ -0,0 +1 @@
+at.asitplus.eidas.specific.modules.auth.idaustria.builder.attributes.EidasConnecorUniqueIdAttributeBuilder
diff --git a/modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties b/modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties
new file mode 100644
index 00000000..6de6e0dc
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties
@@ -0,0 +1,10 @@
+module.idaustria.00=ID Austria authentication-module has an error in configuration. Missing: {0}
+module.idaustria.01=ID Austria authentication-module has an error in configuration: {0}. Reason: {1}
+module.idaustria.02=ID Austria authentication-module has an error in configuration. Reason: {0}
+module.idaustria.03=ID Austria authentication-module has a general error during request pre-processing. Reason: {0}
+module.idaustria.04=ID Austria authentication-module has a general error during response post-processing.
+module.idaustria.05=ID Austria authentication-module can not initialize SAML2 metadata provider for entityId: {0}. Reason: {1}
+module.idaustria.06=ID Austria authentication-module receives an invalid eIDAS bPK, which does NOT match to country-code of eIDAS Proxy-Service
+
+module.idaustria.98=ID Austria authentication-module has an internal error. Reason: {0}
+module.idaustria.99=ID Austria authentication-module has an generic internal error. \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml b/modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml
new file mode 100644
index 00000000..e8a83e68
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<pd:ProcessDefinition id="idAustriaForEidasProxyService"
+ xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1">
+
+ <pd:Task id="createAuthnRequestTask" class="createIdAustriaAuthnRequestTask" />
+ <pd:Task id="receiveAuthnResponseTask" class="receiveIdAustriaAuthnResponseTask" async="true" />
+ <pd:Task id="finalizeAuthentication" class="FinalizeAuthenticationTask" />
+
+ <pd:StartEvent id="start" />
+
+ <pd:Transition from="start" to="createAuthnRequestTask" />
+ <pd:Transition from="createAuthnRequestTask" to="receiveAuthnResponseTask" />
+ <pd:Transition from="receiveAuthnResponseTask" to="finalizeAuthentication" />
+ <pd:Transition from="finalizeAuthentication" to="end" />
+
+ <pd:EndEvent id="end" />
+
+</pd:ProcessDefinition>
diff --git a/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml b/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml
new file mode 100644
index 00000000..d2d16bf9
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml
@@ -0,0 +1,36 @@
+<?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="idAustriaEidasProxyAuthModule"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaEidasProxyAuthenticationModulImpl" />
+
+ <bean id="eiAustriaAuthMessageSource"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.config.IdAustriaAuthMessageSource" />
+
+ <bean id="idAustriaAuthCredentialProvider"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider" />
+
+ <bean id="idAustriaAuthMetadataController"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.controller.IdAustriaAuthMetadataController" />
+
+ <bean id="idAustriaAuthSignalController"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.controller.IdAustriaAuthSignalController" />
+
+ <bean id="idAustriaAuthMetadataProvider"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider" />
+
+ <!-- bean id="eidasAuthHealthCheck"
+ class="at.gv.egiz.eid.authhandler.modules.auth.eidas.utils.EidasCentralAuthHealthCheck" /-->
+
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml b/modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml
new file mode 100644
index 00000000..9da9145d
--- /dev/null
+++ b/modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml
@@ -0,0 +1,23 @@
+<?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 />
+
+ <!-- eIDAS Authentication Process Tasks -->
+ <bean id="createIdAustriaAuthnRequestTask"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.tasks.RequestIdAustriaSystemTask"
+ scope="prototype" />
+
+ <bean id="receiveIdAustriaAuthnResponseTask"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.tasks.ReceiveFromIdAustriaSystemTask"
+ scope="prototype" />
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaAuthSpringResourceProviderTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaAuthSpringResourceProviderTest.java
new file mode 100644
index 00000000..478a3ad4
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaAuthSpringResourceProviderTest.java
@@ -0,0 +1,56 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.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.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthenticationSpringResourceProvider;
+import at.gv.egiz.eaaf.core.test.TestConstants;
+
+
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class IdAustriaAuthSpringResourceProviderTest {
+
+ @Test
+ public void testSpringConfig() {
+ final IdAustriaAuthenticationSpringResourceProvider test =
+ new IdAustriaAuthenticationSpringResourceProvider();
+ 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",
+ IdAustriaAuthenticationSpringResourceProvider.class.getName(), spiFile);
+
+
+ } catch (final IOException e) {
+ Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found");
+
+ }
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaEidasProxyAuthenticationModulImplTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaEidasProxyAuthenticationModulImplTest.java
new file mode 100644
index 00000000..5a4c8b7e
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/IdAustriaEidasProxyAuthenticationModulImplTest.java
@@ -0,0 +1,102 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Before;
+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.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaEidasProxyAuthenticationModulImpl;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.ModuleRegistration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml"})
+@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
+public class IdAustriaEidasProxyAuthenticationModulImplTest {
+
+ @Autowired ModuleRegistration moduleReg;
+ @Autowired ResourceLoader loader;
+ @Autowired ProcessEngine processEngine;
+
+
+ private final ExecutionContext executionContext = new ExecutionContextImpl();
+ private DummySpConfiguration oaParam;
+ private IdAustriaEidasProxyAuthenticationModulImpl authProcess =
+ new IdAustriaEidasProxyAuthenticationModulImpl();
+
+
+ /**
+ * jUnit test set-up.
+ *
+ */
+ @Before
+ public void initialize() {
+ Map<String, String> configMap = new HashMap<String, String>();
+ configMap.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "http://test.com/test");
+ IConfiguration basicConfig = new DummyConfiguration();
+ oaParam = new DummySpConfiguration(configMap, basicConfig);
+
+ }
+
+ @Test
+ public void checkProcessDefinition() {
+ Assert.assertNotNull("AuthModule is null", authProcess);
+ Assert.assertNotNull("AuthModule process is null", authProcess.getProcessDefinitions());
+
+ for (String el : authProcess.getProcessDefinitions()) {
+ Resource res = loader.getResource(el);
+ Assert.assertTrue("AuthProcess description not extist", res.exists());
+
+ }
+ }
+
+ @Test
+ public void idAustriaAuthSelected() throws Exception {
+ ProxyServicePendingRequest pendingReq = new ProxyServicePendingRequest();
+ pendingReq.setOnlineApplicationConfiguration(oaParam);
+
+ //execute test
+ final String result = moduleReg.selectProcess(executionContext, pendingReq);
+
+ //validate state
+ Assert.assertNotNull("Process is null", result);
+ Assert.assertEquals("Process Id not match", "idAustriaForEidasProxyService", result);
+
+ Assert.assertNotNull("Can not initalize process", processEngine.createProcessInstance(result));
+
+ }
+
+ @Test
+ public void wrongPendingRequestType() throws Exception {
+ TestRequestImpl pendingReq = new TestRequestImpl();
+ pendingReq.setSpConfig(oaParam);
+
+ //execute test
+ final String result = moduleReg.selectProcess(executionContext, pendingReq);
+
+ //validate state
+ Assert.assertNull("AuthProcessName", result);
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/EidasConnecorUniqueIdAttributeBuilderTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/EidasConnecorUniqueIdAttributeBuilderTest.java
new file mode 100644
index 00000000..9f42f5e5
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/EidasConnecorUniqueIdAttributeBuilderTest.java
@@ -0,0 +1,54 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.builder.attributes;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.builder.attributes.EidasConnecorUniqueIdAttributeBuilder;
+import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.attributes.AbstractAttributeBuilderTest;
+
+/**
+ * Attribute builder to generate an attribute that holds the unique eIDSA-Connector identifier for this process.
+ * <br>
+ * The attribute-value is read from {@link ISpConfiguration} with method <code>getUniqueIdentifier()</code>
+ *
+ * @author tlenz
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ "/spring/SpringTest-context_basic_test.xml",
+})
+public class EidasConnecorUniqueIdAttributeBuilderTest extends AbstractAttributeBuilderTest {
+
+ private final IAttributeBuilder attrBuilder = new EidasConnecorUniqueIdAttributeBuilder();
+
+ @Test
+ public void attributeName() {
+ Assert.assertEquals("Wrong attribute name",
+ "urn:eidgvat:attributes.eidas.uniqueId", attrBuilder.getName());
+
+ }
+
+ @Test
+ public void checkEmptyAttribute() {
+ String value = attrBuilder.buildEmpty(gen);
+ Assert.assertNull("Attr. not null", value);
+
+ }
+
+
+ @Test
+ public void withAttributeValue() throws AttributeBuilderException, Exception {
+ String value = attrBuilder.build(spConfig, buildAuthData(), gen);
+ Assert.assertEquals("wrong attributeValue", spConfig.getUniqueIdentifier(), value);
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/config/IdAustriaAuthMessageSourceTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/config/IdAustriaAuthMessageSourceTest.java
new file mode 100644
index 00000000..2a92c01e
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/config/IdAustriaAuthMessageSourceTest.java
@@ -0,0 +1,50 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.config;
+
+import java.util.List;
+
+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;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.config.IdAustriaAuthMessageSource;
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+public class IdAustriaAuthMessageSourceTest {
+
+ @Autowired
+ private ResourceLoader loader;
+ @Autowired(required = false)
+ private List<IMessageSourceLocation> messageSources;
+
+ @Test
+ public void checkMessageSources() {
+ Assert.assertNotNull("No messageSource", messageSources);
+ Assert.assertFalse("No message source", messageSources.isEmpty());
+
+ boolean found = false;
+
+ for (final IMessageSourceLocation messageSource : messageSources) {
+ found = found ? found : messageSource instanceof IdAustriaAuthMessageSource;
+
+ 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());
+
+ }
+ }
+
+ Assert.assertTrue("Internal messagesource not found", found);
+
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java
new file mode 100644
index 00000000..0df74f7b
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java
@@ -0,0 +1,186 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.controller;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+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.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.metadata.resolver.filter.FilterException;
+import org.opensaml.saml.metadata.resolver.filter.MetadataFilterContext;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.security.x509.BasicX509Credential;
+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.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.controller.IdAustriaAuthMetadataController;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter;
+import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ "/spring/SpringTest-context_basic_test.xml"
+})
+@EnableWebMvc
+public class IdAustriaAuthMetadataControllerFirstTest {
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+
+ @Autowired private IdAustriaAuthMetadataController controller;
+ @Autowired private IdAustriaAuthCredentialProvider credProvider;
+ @Autowired private MsConnectorDummyConfigMap config;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void initialize() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * Single jUnit-test set-up.
+ */
+ @Before
+ public void testSetup() {
+ httpReq = new MockHttpServletRequest("GET", "https://localhost/authhandler");
+ httpReq.setContextPath("/authhandler");
+ httpResp = new MockHttpServletResponse();
+
+ //remove additional attributes
+ Map<String, String> attr = config.getBasicConfigurationWithPrefix(
+ "eidas.ms.modules.idaustriaauth.required.additional.attributes.");
+ for (String el : attr.keySet()) {
+ config.removeConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes." + el);
+
+ }
+
+
+ }
+
+ @Test
+ public void buildMetadataValid() throws IOException, EaafException,
+ XMLParserException, UnmarshallingException, FilterException {
+
+ //build metdata
+ controller.getSpMetadata(httpReq, httpResp);
+
+ //check result
+ validateResponse(16);
+
+ }
+
+ @Test
+ public void buildMetadataValidWithAdditionalAttributes() throws IOException, EaafException,
+ XMLParserException, UnmarshallingException, FilterException {
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.1",
+ PvpAttributeDefinitions.BPK_LIST_NAME + ",true");
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.2",
+ PvpAttributeDefinitions.PVP_VERSION_NAME + ",false");
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.7",
+ PvpAttributeDefinitions.EID_SIGNER_CERTIFICATE_NAME + ",true");
+
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.3", "bbbbb");
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.4", "bbbbb,false,test");
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.5", "bbbbb,nichts");
+ config.putConfigValue("eidas.ms.modules.idaustriaauth.required.additional.attributes.6", "");
+
+ //build metdata
+ controller.getSpMetadata(httpReq, httpResp);
+
+ //check result
+ validateResponse(17);
+
+ }
+
+ private void validateResponse(int numberOfRequestedAttributes) throws UnsupportedEncodingException,
+ XMLParserException, UnmarshallingException, FilterException, CredentialsNotAvailableException {
+ Assert.assertEquals("HTTP Statuscode", 200, httpResp.getStatus());
+ Assert.assertEquals("ContentType", "text/xml; charset=utf-8", httpResp.getContentType());
+ Assert.assertEquals("ContentEncoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String metadataXml = httpResp.getContentAsString();
+ Assert.assertNotNull("XML Metadata", metadataXml);
+
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(), new ByteArrayInputStream(metadataXml.getBytes("UTF-8")));
+
+ Assert.assertEquals("EntityId",
+ "http://localhost/authhandler" + IdAustriaAuthConstants.ENDPOINT_METADATA,
+ metadata.getEntityID());
+
+ MetadataFilterContext filterContext = new MetadataFilterContext();
+
+ //check XML scheme
+ final SchemaValidationFilter schemaFilter = new SchemaValidationFilter();
+ schemaFilter.filter(metadata, filterContext);
+
+ //check signature
+ final SimpleMetadataSignatureVerificationFilter sigFilter =
+ new SimpleMetadataSignatureVerificationFilter(credProvider.getKeyStore().getFirst(),
+ metadata.getEntityID());
+ sigFilter.filter(metadata, filterContext);
+
+ //check content
+ final SPSSODescriptor spSsoDesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
+ Assert.assertNotNull("SPSSODescr.", spSsoDesc);
+
+ Assert.assertFalse("AssertionConsumerServices",
+ spSsoDesc.getAssertionConsumerServices().isEmpty());
+ Assert.assertTrue("ContactPersons", metadata.getContactPersons().isEmpty());
+ Assert.assertNull("ContactPersons", metadata.getOrganization());
+
+ Assert.assertFalse("KeyDescriptors",
+ spSsoDesc.getKeyDescriptors().isEmpty());
+ Assert.assertEquals("#KeyDescriptors", 2, spSsoDesc.getKeyDescriptors().size());
+
+ Assert.assertFalse("NameIDFormats",
+ spSsoDesc.getNameIDFormats().isEmpty());
+ Assert.assertEquals("wrong NameIDFormats", "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
+ spSsoDesc.getNameIDFormats().get(0).getURI());
+
+ Assert.assertFalse("AttributeConsumingServices",
+ spSsoDesc.getAttributeConsumingServices().isEmpty());
+ Assert.assertEquals("#RequestAttributes", numberOfRequestedAttributes,
+ spSsoDesc.getAttributeConsumingServices().get(0).getRequestedAttributes().size());
+
+ }
+
+ private List<BasicX509Credential> convertX509Certs(List<X509Certificate> certs) {
+ final List<BasicX509Credential> result = new ArrayList<>();
+ for (final X509Certificate cert : certs) {
+ result.add(new BasicX509Credential(cert));
+
+ }
+ return result;
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthSignalControllerTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthSignalControllerTest.java
new file mode 100644
index 00000000..e9ecbc58
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthSignalControllerTest.java
@@ -0,0 +1,200 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.controller;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+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.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.SerializationUtils;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.controller.IdAustriaAuthSignalController;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.ExceptionContainer;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyProtocolAuthService;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.spring.test.DummyTransactionStorage.DummyDbEntry;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ "/spring/SpringTest-context_basic_test.xml"
+})
+@EnableWebMvc
+public class IdAustriaAuthSignalControllerTest {
+
+ @Autowired(required = true)
+ private IdAustriaAuthSignalController controller;
+ @Autowired(required = true)
+ private ITransactionStorage cache;
+ @Autowired(required = true)
+ private IPendingRequestIdGenerationStrategy pendingReqGeneration;
+ @Autowired(required = true)
+ private IRequestStorage reqStorage;
+ @Autowired(required = true)
+ private IConfiguration basicConfig;
+ @Autowired private ITransactionStorage transactionStorage;
+
+ @Autowired private DummyProtocolAuthService protAuthService;
+
+ @Test
+ public void noRelayState() throws IOException, EaafException {
+ final MockHttpServletRequest httpReq =
+ new MockHttpServletRequest("POST", "https://localhost/ms_connectoror");
+ final MockHttpServletResponse httpResp = new MockHttpServletResponse();
+
+ controller.performEidasAuthentication(httpReq, httpResp);
+ Assert.assertEquals("httpStausCode", 200, httpResp.getStatus());
+
+ final String errorId = protAuthService.getErrorKey();
+ final Object error = cache.get(errorId);
+ Assert.assertNotNull("Error is null", error);
+ org.springframework.util.Assert.isInstanceOf(byte[].class,
+ ((DummyDbEntry) error).getObj());
+ final Object errorObj = SerializationUtils.deserialize((byte[]) ((DummyDbEntry) error).getObj());
+ org.springframework.util.Assert.isInstanceOf(ExceptionContainer.class, errorObj);
+ org.springframework.util.Assert.isInstanceOf(EaafException.class,
+ ((ExceptionContainer) errorObj).getExceptionThrown());
+
+ }
+
+ @Test
+ public void validRelayStateNoPendingReqId() throws EaafException, IOException {
+ final String pendingReqId = pendingReqGeneration.generateExternalPendingRequestId();
+ final MockHttpServletRequest httpReq =
+ new MockHttpServletRequest("POST", "https://localhost/ms_connectoror");
+ httpReq.addParameter(IdAustriaAuthSignalController.HTTP_PARAM_RELAYSTATE, pendingReqId);
+ final MockHttpServletResponse httpResp = new MockHttpServletResponse();
+
+ controller.performEidasAuthentication(httpReq, httpResp);
+ Assert.assertEquals("httpStausCode", 200, httpResp.getStatus());
+
+ final String errorId = protAuthService.getErrorKey();
+ final Object error = cache.get(errorId);
+ Assert.assertNotNull("Error is null", error);
+ org.springframework.util.Assert.isInstanceOf(byte[].class,
+ ((DummyDbEntry) error).getObj());
+ final Object errorObj = SerializationUtils.deserialize((byte[]) ((DummyDbEntry) error).getObj());
+ org.springframework.util.Assert.isInstanceOf(ExceptionContainer.class, errorObj);
+ org.springframework.util.Assert.isInstanceOf(EaafException.class,
+ ((ExceptionContainer) errorObj).getExceptionThrown());
+ //TODO:
+ Assert.assertEquals("ErrorCode not match", "auth.26",
+ ((EaafException) ((ExceptionContainer) errorObj).getExceptionThrown()).getErrorId());
+
+ }
+
+ @Test
+ public void validRelayStateSuspectPendingReqId() throws EaafException, IOException {
+ String relayState = RandomStringUtils.randomAlphanumeric(10);
+ transactionStorage.put(relayState, false, -1);
+
+ final MockHttpServletRequest httpReq =
+ new MockHttpServletRequest("POST", "https://localhost/ms_connectoror");
+ httpReq.addParameter(IdAustriaAuthSignalController.HTTP_PARAM_RELAYSTATE, relayState);
+ final MockHttpServletResponse httpResp = new MockHttpServletResponse();
+
+ controller.performEidasAuthentication(httpReq, httpResp);
+ Assert.assertEquals("httpStausCode", 200, httpResp.getStatus());
+
+ final String errorId = protAuthService.getErrorKey();
+ final Object error = cache.get(errorId);
+ Assert.assertNotNull("Error is null", error);
+ org.springframework.util.Assert.isInstanceOf(byte[].class,
+ ((DummyDbEntry) error).getObj());
+ final Object errorObj = SerializationUtils.deserialize((byte[]) ((DummyDbEntry) error).getObj());
+ org.springframework.util.Assert.isInstanceOf(ExceptionContainer.class, errorObj);
+ org.springframework.util.Assert.isInstanceOf(EaafException.class,
+ ((ExceptionContainer) errorObj).getExceptionThrown());
+ //TODO:
+ Assert.assertEquals("ErrorCode not match", "auth.26",
+ ((EaafException) ((ExceptionContainer) errorObj).getExceptionThrown()).getErrorId());
+
+ Assert.assertNull("RelayState was not removed", transactionStorage.get(relayState));
+
+ }
+
+ @Test
+ public void validRelayStateNoPendingReq() throws EaafException, IOException {
+ final String pendingReqId = pendingReqGeneration.generateExternalPendingRequestId();
+ String relayState = RandomStringUtils.randomAlphanumeric(10);
+ transactionStorage.put(relayState, pendingReqId, -1);
+
+ final MockHttpServletRequest httpReq =
+ new MockHttpServletRequest("POST", "https://localhost/ms_connectoror");
+ httpReq.addParameter(IdAustriaAuthSignalController.HTTP_PARAM_RELAYSTATE, relayState);
+ final MockHttpServletResponse httpResp = new MockHttpServletResponse();
+
+ controller.performEidasAuthentication(httpReq, httpResp);
+ Assert.assertEquals("httpStausCode", 200, httpResp.getStatus());
+
+ final String errorId = protAuthService.getErrorKey();
+ final Object error = cache.get(errorId);
+ Assert.assertNotNull("Error is null", error);
+ org.springframework.util.Assert.isInstanceOf(byte[].class,
+ ((DummyDbEntry) error).getObj());
+ final Object errorObj = SerializationUtils.deserialize((byte[]) ((DummyDbEntry) error).getObj());
+ org.springframework.util.Assert.isInstanceOf(ExceptionContainer.class, errorObj);
+ org.springframework.util.Assert.isInstanceOf(EaafException.class,
+ ((ExceptionContainer) errorObj).getExceptionThrown());
+ //TODO:
+ Assert.assertEquals("ErrorCode not match", "auth.28",
+ ((EaafException) ((ExceptionContainer) errorObj).getExceptionThrown()).getErrorId());
+
+ Assert.assertNull("RelayState was not removed", transactionStorage.get(relayState));
+
+ }
+
+ @Test
+ public void validRelayStateWithPendingReq() throws EaafException, IOException {
+ final String pendingReqId = pendingReqGeneration.generateExternalPendingRequestId();
+
+ String relayState = RandomStringUtils.randomAlphanumeric(10);
+ transactionStorage.put(relayState, pendingReqId, -1);
+
+ final TestRequestImpl pendingReq = new TestRequestImpl();
+ pendingReq.setPendingReqId(pendingReqId);
+ pendingReq.setAuthUrl("http://localhost/idp");
+ final Map<String, String> spConfigMap = new HashMap<>();
+ spConfigMap.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "http://test.sp");
+ final DummySpConfiguration spConfig = new DummySpConfiguration(spConfigMap, basicConfig);
+ pendingReq.setSpConfig(spConfig);
+ reqStorage.storePendingRequest(pendingReq);
+
+ final MockHttpServletRequest httpReq =
+ new MockHttpServletRequest("POST", "https://localhost/ms_connectoror");
+ httpReq.addParameter(IdAustriaAuthSignalController.HTTP_PARAM_RELAYSTATE, relayState);
+ final MockHttpServletResponse httpResp = new MockHttpServletResponse();
+
+ controller.performEidasAuthentication(httpReq, httpResp);
+
+ Assert.assertEquals("httpStausCode", 200, httpResp.getStatus());
+
+ final String errorId = protAuthService.getErrorKey();
+ final Object error = cache.get(errorId);
+ Assert.assertNotNull("Error is null", error);
+ org.springframework.util.Assert.isInstanceOf(byte[].class,
+ ((DummyDbEntry) error).getObj());
+ final Object errorObj = SerializationUtils.deserialize((byte[]) ((DummyDbEntry) error).getObj());
+ org.springframework.util.Assert.isInstanceOf(ExceptionContainer.class, errorObj);
+ org.springframework.util.Assert.isInstanceOf(EaafException.class,
+ ((ExceptionContainer) errorObj).getExceptionThrown());
+ Assert.assertEquals("ErrorCode not match",
+ "PendingRequest object is not of type 'RequestImpl.class'",
+ ((EaafException) ((ExceptionContainer) errorObj).getExceptionThrown()).getErrorId());
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java
new file mode 100644
index 00000000..c452fe22
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java
@@ -0,0 +1,792 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.task;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.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.Issuer;
+import org.opensaml.saml.saml2.core.Response;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.tasks.ReceiveFromIdAustriaSystemTask;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.IRequestStorage;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+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.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.sp.exception.AuthnResponseValidationException;
+import net.shibboleth.utilities.java.support.xml.XMLParserException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ "/spring/SpringTest-context_basic_test.xml",
+})
+public class ReceiveAuthnResponseTaskTest {
+
+ private static final String METADATA_PATH = "classpath:/data/idp_metadata_classpath_entity.xml";
+
+ @Autowired ApplicationContext context;
+ @Autowired MsConnectorDummyConfigMap config;
+
+ @Autowired IdAustriaAuthMetadataProvider metadataProvider;
+ @Autowired IdAustriaAuthCredentialProvider credentialProvider;
+ @Autowired PvpMetadataResolverFactory metadataFactory;
+ @Autowired IRequestStorage storage;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+
+ private ProxyServicePendingRequest pendingReq;
+ private ServiceProviderConfiguration oaParam;
+ private Map<String, String> spConfig;
+
+ private ReceiveFromIdAustriaSystemTask task;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void initialize() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * jUnit test set-up.
+ *
+ * @throws Exception In case of an set-up error
+ */
+ @Before
+ public void setUp() throws Exception {
+ task = (ReceiveFromIdAustriaSystemTask) context.getBean("receiveIdAustriaAuthnResponseTask");
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector");
+ httpReq.setScheme("https");
+ httpReq.setServerPort(443);
+ httpReq.setContextPath("/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID,
+ "classpath:/data/idp_metadata_classpath_entity.xml");
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS, "sig");
+
+ spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "http://test.com/test");
+ oaParam = new ServiceProviderConfiguration(spConfig, config);
+ oaParam.setRequiredLoA(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+
+ pendingReq = new ProxyServicePendingRequest();
+ pendingReq.initialize(httpReq, config);
+ pendingReq.setPendingRequestId(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setOnlineApplicationConfiguration(oaParam);
+
+ metadataProvider.fullyDestroy();
+
+ }
+
+ @Test
+ public void unsupportedHttpMethode() {
+ httpReq = new MockHttpServletRequest("PUT", "https://localhost/ms_connector");
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.03",
+ ((AuthnResponseValidationException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpGetNoMessage() {
+ httpReq = new MockHttpServletRequest("GET", "https://localhost/ms_connector");
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((AuthnResponseValidationException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostNoMessage() {
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((AuthnResponseValidationException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostMessageNotSigned() throws IOException {
+
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ IOUtils.toByteArray(ReceiveAuthnResponseTaskTest.class.getResourceAsStream(
+ "/data/Response_without_sig_classpath_entityid.xml"))));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((AuthnResponseValidationException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostMessageWrongDestinationEndpoint() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ TransformerException, MarshallingException {
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_wrong_destination_endpoint.xml",
+ credentialProvider.getMessageSigningCredential(), true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((AuthnResponseValidationException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedNoMetadata() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException {
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_classpath_entityid.xml",
+ credentialProvider.getMessageSigningCredential(), true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.11",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionOutDated() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_classpath_entityid.xml",
+ credentialProvider.getMessageSigningCredential(), false);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionFromWrongIdp() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID,
+ RandomStringUtils.randomAlphabetic(10));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_classpath_entityid.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.08",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedWitError() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_with_error.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.05",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedWitUserStopErrorCode() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_with_error_userstop.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform test
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ Assert.assertTrue("process not cancelled", executionContext.isProcessCancelled());
+ Assert.assertTrue("process not stopped by user", pendingReq.isAbortedByUser());
+ Assert.assertFalse("should not authenticated", pendingReq.isAuthenticated());
+
+ }
+
+ @Test
+ public void httpPostValidSignedWithErrorAndNoSubCode() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_with_error_without_subcode.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.05",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedWithErrorAndEmptySubCode() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_without_sig_with_error_empty_subcode.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.05",
+ ((EaafException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionMissingAttributes() throws IOException, SamlSigningException,
+ Pvp2MetadataException, CredentialsNotAvailableException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException {
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID_wrong_data.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((EaafException) e.getOriginalException()).getErrorId());
+ Assert.assertEquals("sp.pvp2.06",
+ ((EaafException) ((EaafException) e.getOriginalException()).getCause()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionWrongBpkTarget() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+ZZ");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ final TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(AuthnResponseValidationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("sp.pvp2.12",
+ ((EaafException) e.getOriginalException()).getErrorId());
+ Assert.assertEquals("sp.pvp2.06",
+ ((EaafException) ((EaafException) e.getOriginalException()).getCause()).getErrorId());
+ Assert.assertEquals("module.idaustria.06",
+ ((EaafException) ((EaafException) ((EaafException) e.getOriginalException())
+ .getCause()).getCause()).getErrorId());
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionEidValid() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+XX");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertFalse("foreigner flag", session.isForeigner());
+ assertTrue("eidProcess flag", session.isEidProcess());
+ assertFalse("useMandate flag", session.isMandateUsed());
+
+ checkAttributeInSession(session,PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max");
+ checkAttributeInSession(session,PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann");
+ checkAttributeInSession(session,PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/high");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT");
+
+ //pre-generated eIDAS identifer
+ checkAttributeInSession(session, MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcM4UcyhDTNGYmVdrIoY=");
+
+ }
+
+
+
+ @Test
+ public void httpPostValidSignedAssertionMinimumAttributes() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+CC");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID_minimum.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertFalse("foreigner flag", session.isForeigner());
+
+ checkAttributeInSession(session,PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max");
+ checkAttributeInSession(session,PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann");
+ checkAttributeInSession(session,PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT");
+
+ checkAttributeInSession(session,MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcM4UcyhDTNGYmVdrIoY=");
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionEidBpkWithoutPrefix() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+XX");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID_bpk_without_prefix.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertFalse("foreigner flag", session.isForeigner());
+
+ checkAttributeInSession(session,PvpAttributeDefinitions.GIVEN_NAME_NAME, "Susi");
+ checkAttributeInSession(session,PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Heinz");
+ checkAttributeInSession(session,PvpAttributeDefinitions.BIRTHDATE_NAME, "1955-01-01");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/aabbcc");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT");
+
+ //pre-generated eIDAS identifer
+ checkAttributeInSession(session,MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY=");
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionEidWithEidSectorAttr() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+AB");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID_with_eid_sector_attr.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertFalse("foreigner flag", session.isForeigner());
+
+ checkAttributeInSession(session,PvpAttributeDefinitions.GIVEN_NAME_NAME, "Susi");
+ checkAttributeInSession(session,PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Heinz");
+ checkAttributeInSession(session,PvpAttributeDefinitions.BIRTHDATE_NAME, "1955-01-01");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/aabbcc");
+ checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT");
+
+ //pre-generated eIDAS identifer
+ checkAttributeInSession(session,MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY=");
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionEidValidWithJurMandate() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+XX");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID_with_mandate_jur.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertFalse("foreigner flag", session.isForeigner());
+ assertTrue("eidProcess flag", session.isEidProcess());
+ assertTrue("useMandate flag", session.isMandateUsed());
+
+ checkAttributeInSession(session, PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max");
+ checkAttributeInSession(session, PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann");
+ checkAttributeInSession(session, PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01");
+ checkAttributeInSession(session, PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/high");
+ checkAttributeInSession(session, PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT");
+
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_TYPE_NAME, "Generalvollmacht");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, "Testfirma");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, "999999m");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, "urn:publicid:gv.at:baseid+XERSB");
+
+ //pre-generated eIDAS identifer
+ checkAttributeInSession(session, MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcM4UcyhDTNGYmVdrIoY=");
+ assertNull("find nat. person bpk for mandator", session.getGenericDataFromSession(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, String.class));
+
+
+ }
+
+ @Test
+ public void httpPostValidSignedAssertionEidValidWithNatMandate() throws IOException, XMLParserException, UnmarshallingException,
+ MarshallingException, TransformerException, TaskExecutionException, EaafException {
+
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+XX");
+
+ metadataProvider.addMetadataResolverIntoChain(metadataFactory.createMetadataProvider(
+ METADATA_PATH, null, "jUnit IDP", null));
+
+ final Response response = initializeResponse(
+ "classpath:/data/idp_metadata_classpath_entity.xml",
+ "/data/Response_with_EID_with_mandate_nat.xml",
+ credentialProvider.getMessageSigningCredential(),
+ true);
+ httpReq.addParameter("SAMLResponse", Base64.getEncoder().encodeToString(
+ DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes(
+ "UTF-8")));
+
+ // perform task
+ task.execute(pendingReq, executionContext);
+
+ // validate state
+ IRequest storedReq = storage.getPendingRequest(pendingReq.getPendingRequestId());
+ Assert.assertNotNull("pendingReq not stored", storedReq);
+ final AuthProcessDataWrapper session = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ Assert.assertFalse("foreigner flag", session.isForeigner());
+ assertTrue("eidProcess flag", session.isEidProcess());
+ assertTrue("useMandate flag", session.isMandateUsed());
+
+ checkAttributeInSession(session, PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max");
+ checkAttributeInSession(session, PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann");
+ checkAttributeInSession(session, PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01");
+ checkAttributeInSession(session, PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/high");
+ checkAttributeInSession(session, PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT");
+
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_TYPE_NAME, "GeneralvollmachtBilateral");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, "Gerti");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, "Musterfrau");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "01-02-1941");
+ checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, "AT+XX:AFSDAFSDFDSFCSDAFASDF=");
+
+
+ //pre-generated eIDAS identifer
+ checkAttributeInSession(session, MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "QVGm48cqcM4UcyhDTNGYmVdrIoY=");
+
+
+ }
+
+ private void checkAttributeInSession(AuthProcessDataWrapper session, String attrName, String expected) {
+ String value = session.getGenericDataFromSession(attrName, String.class);
+ Assert.assertEquals("wrong attr. value", expected, value);
+
+ }
+
+ private Response initializeResponse(String idpEntityId, String responsePath, EaafX509Credential credential,
+ boolean validConditions) throws SamlSigningException, XMLParserException, UnmarshallingException,
+ Pvp2MetadataException {
+
+ final Response response = (Response) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ ReceiveAuthnResponseTaskTest.class.getResourceAsStream(responsePath));
+ response.setIssueInstant(Instant.now());
+ final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class);
+ issuer.setValue(idpEntityId);
+ response.setIssuer(issuer);
+
+ if (validConditions) {
+ response.getAssertions().get(0).getConditions().setNotOnOrAfter(Instant.now().plusSeconds(5*60));
+
+ }
+
+ return Saml2Utils.signSamlObject(response, credential, true);
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java
new file mode 100644
index 00000000..54b019eb
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java
@@ -0,0 +1,455 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.task;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.core.xml.schema.XSString;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.tasks.RequestIdAustriaSystemTask;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes;
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+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.Pvp2InternalErrorException;
+import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException;
+import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest;
+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.binding.PostBindingTest;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ "/spring/SpringTest-context_basic_test.xml",
+})
+public class RequestIdAustriaSystemTaskTest {
+
+ private static final String METADATA_PATH = "classpath:/data/idp_metadata_classpath_entity.xml";
+ private static final String METADATA_SP_PATH = "classpath:/data/sp_metadata_junit.xml";
+
+ @Autowired ApplicationContext context;
+ @Autowired MsConnectorDummyConfigMap config;
+ @Autowired IdAustriaAuthMetadataProvider metadataProvider;
+ @Autowired PvpMetadataResolverFactory metadataFactory;
+ @Autowired DummyGuiBuilderConfigurationFactory guiBuilderConfigFactory;
+ @Autowired SamlVerificationEngine samlVerifyEngine;
+ @Autowired ITransactionStorage transactionStorage;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private ProxyServicePendingRequest pendingReq;
+ private ServiceProviderConfiguration oaParam;
+ private Map<String, String> spConfig;
+
+ private RequestIdAustriaSystemTask task;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void initialize() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * jUnit test set-up.
+ *
+ * @throws Exception In case of an set-up error
+ */
+ @Before
+ public void setUp() throws Exception {
+ task = (RequestIdAustriaSystemTask) context.getBean("createIdAustriaAuthnRequestTask");
+
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS, "sig");
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID, METADATA_PATH);
+
+ spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "http://test.com/test");
+ oaParam = new ServiceProviderConfiguration(spConfig, config);
+ oaParam.setRequiredLoA(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ oaParam.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_EIDAS + "AT+"
+ + spCountryCode);
+
+ pendingReq = new ProxyServicePendingRequest();
+ pendingReq.initialize(httpReq, config);
+ pendingReq.setPendingRequestId(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setOnlineApplicationConfiguration(oaParam);
+
+ metadataProvider.fullyDestroy();
+ guiBuilderConfigFactory.setVelocityBuilderConfig(createDummyGuiConfig());
+
+ }
+
+ @Test
+ public void missingIdAustriaSystemEntiryId() {
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID);
+
+
+ TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("module.idaustria.00",
+ ((EaafConfigurationException) e.getOriginalException()).getErrorId());
+
+
+ }
+
+ @Test
+ public void noMetadataAvailableOnGlobalConfig() {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID,
+ RandomStringUtils.randomAlphabetic(10));
+
+
+ TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,
+ e.getOriginalException());
+ Assert.assertEquals("module.idaustria.05",
+ ((EaafConfigurationException) e.getOriginalException()).getErrorId());
+
+
+ }
+
+ @Test
+ public void noMetadataSigningKeyStore() throws Pvp2MetadataException {
+ config.removeConfigValue("eidas.ms.modules.idaustriaauth.request.sign.alias");
+
+ metadataProvider.addMetadataResolverIntoChain(
+ metadataFactory.createMetadataProvider(METADATA_PATH, null, "jUnitTest", null));
+
+ TaskExecutionException e = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Assert.assertNotNull(e.getPendingRequestID());
+ Assert.assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID());
+ Assert.assertNotNull(e.getOriginalException());
+ org.springframework.util.Assert.isInstanceOf(CredentialsNotAvailableException.class,
+ e.getOriginalException());
+ Assert.assertEquals("internal.pvp.01",
+ ((CredentialsNotAvailableException) e.getOriginalException()).getErrorId());
+
+ }
+
+ @Test
+ public void successWithoutSpInfos() throws Pvp2InternalErrorException, SecurityException, Exception {
+ metadataProvider.addMetadataResolverIntoChain(
+ metadataFactory.createMetadataProvider(METADATA_PATH, null, "jUnitTest", null));
+
+ LightRequest.Builder eidasRequestBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public");
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ final EaafRequestedAttributes reqAttr = validate();
+ Assert.assertEquals("#Req Attribute", 4, reqAttr.getAttributes().size());
+
+ Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.eidas.uniqueId",
+ reqAttr.getAttributes().get(0).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(0).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(0).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(0).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value", pendingReq.getServiceProviderConfiguration().getUniqueIdentifier(),
+ ((XSString)reqAttr.getAttributes().get(0).getAttributeValues().get(0)).getValue());
+
+ Assert.assertEquals("Wrong req attr.", "urn:oid:1.2.40.0.10.2.1.1.261.34",
+ reqAttr.getAttributes().get(1).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(1).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(1).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value", oaParam.getAreaSpecificTargetIdentifier(),
+ ((XSString)reqAttr.getAttributes().get(1).getAttributeValues().get(0)).getValue());
+
+ Assert.assertEquals("Wrong req attr.", "urn:oid:1.2.40.0.10.2.1.1.261.108",
+ reqAttr.getAttributes().get(2).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(2).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(2).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value", "http://eidas.europa.eu/LoA/high",
+ ((XSString)reqAttr.getAttributes().get(2).getAttributeValues().get(0)).getValue());
+
+ Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderMandateType",
+ reqAttr.getAttributes().get(3).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(3).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(3).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(3).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value",
+ pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).getMandateMode().getMode(),
+ ((XSString)reqAttr.getAttributes().get(3).getAttributeValues().get(0)).getValue());
+
+ }
+
+ @Test
+ public void successWithSpInfos() throws Pvp2InternalErrorException, SecurityException, Exception {
+ metadataProvider.addMetadataResolverIntoChain(
+ metadataFactory.createMetadataProvider(METADATA_PATH, null, "jUnitTest", null));
+
+ LightRequest.Builder eidasRequestBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requesterId(RandomStringUtils.randomAlphanumeric(10))
+ .providerName(RandomStringUtils.randomAlphanumeric(10));
+ LightRequest eidasReq = eidasRequestBuilder.build();
+ pendingReq.setEidasRequest(eidasReq);
+
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ final EaafRequestedAttributes reqAttr = validate();
+ Assert.assertEquals("#Req Attribute", 6, reqAttr.getAttributes().size());
+
+ Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderFriendlyName",
+ reqAttr.getAttributes().get(3).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(3).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(3).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value", eidasReq.getProviderName(),
+ ((XSString)reqAttr.getAttributes().get(3).getAttributeValues().get(0)).getValue());
+
+ Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderUniqueId",
+ reqAttr.getAttributes().get(4).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(4).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(4).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value", eidasReq.getRequesterId(),
+ ((XSString)reqAttr.getAttributes().get(4).getAttributeValues().get(0)).getValue());
+
+ }
+
+ @Test
+ public void successWithMandates() throws Pvp2InternalErrorException, SecurityException, Exception {
+ metadataProvider.addMetadataResolverIntoChain(
+ metadataFactory.createMetadataProvider(METADATA_PATH, null, "jUnitTest", null));
+
+ LightRequest.Builder eidasRequestBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requesterId(RandomStringUtils.randomAlphanumeric(10))
+ .providerName(RandomStringUtils.randomAlphanumeric(10));
+ LightRequest eidasReq = eidasRequestBuilder.build();
+ pendingReq.setEidasRequest(eidasReq);
+
+ List<String> mandateProfiles = Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ oaParam.setMandateProfiles(mandateProfiles);
+ oaParam.setMandateMode(SpMandateModes.LEGAL_FORCE);
+ //execute test
+ task.execute(pendingReq, executionContext);
+
+ //validate state
+ final EaafRequestedAttributes reqAttr = validate();
+ Assert.assertEquals("#Req Attribute", 7, reqAttr.getAttributes().size());
+
+ Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderMandateProfiles",
+ reqAttr.getAttributes().get(5).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(5).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(5).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+
+ List<String> reqProfiles = KeyValueUtils.getListOfCsvValues(
+ ((XSString)reqAttr.getAttributes().get(5).getAttributeValues().get(0)).getValue());
+ reqProfiles.stream().forEach(el -> assertTrue("missing profile: " + el, mandateProfiles.contains(el)));
+
+
+ Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderMandateType",
+ reqAttr.getAttributes().get(6).getName());
+ Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(6).getAttributeValues());
+ Assert.assertEquals("#Req. Attr value", 1,
+ reqAttr.getAttributes().get(6).getAttributeValues().size());
+ org.springframework.util.Assert.isInstanceOf(XSString.class,
+ reqAttr.getAttributes().get(6).getAttributeValues().get(0), "Wrong requested Attributes Value type");
+ Assert.assertEquals("Req. Attr. Value",
+ SpMandateModes.LEGAL_FORCE.getMode(),
+ ((XSString)reqAttr.getAttributes().get(6).getAttributeValues().get(0)).getValue());
+
+ }
+
+ private EaafRequestedAttributes validate() throws Pvp2InternalErrorException, SecurityException, Exception {
+ Assert.assertEquals("HTTP Statuscode", 200, httpResp.getStatus());
+ Assert.assertEquals("ContentType", "text/html;charset=UTF-8", httpResp.getContentType());
+ Assert.assertEquals("ContentEncoding", "UTF-8", httpResp.getCharacterEncoding());
+
+ final String html = httpResp.getContentAsString();
+ Assert.assertNotNull("XML Metadata", html);
+
+ final int startIndex = html.indexOf("SAMLRequest=");
+ Assert.assertTrue("No SAMLRequest in html", startIndex >= 0);
+ final String authnXml = html.substring(startIndex + "SAMLRequest=".length());
+
+ //check if relaystate was stored
+ final int startIndexRelayState = html.indexOf("RelayState=");
+ Assert.assertTrue("wrong RelayState in HTML",
+ startIndexRelayState >= 0);
+ String relayState = html.substring(startIndexRelayState + "RelayState=".length(), startIndex);
+ String storedPendingReqId = transactionStorage.get(relayState, String.class);
+ Assert.assertEquals("relayStore not map to pendingRequestId",
+ pendingReq.getPendingRequestId(), storedPendingReqId);
+
+
+ final AuthnRequest authnRequest = (AuthnRequest) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(), new ByteArrayInputStream(
+ Base64.getDecoder().decode(authnXml)));
+
+ Assert.assertNotNull("AuthnReq", authnRequest);
+ Assert.assertNotNull("Issuer", authnRequest.getIssuer());
+ Assert.assertEquals("EntityId",
+ "http://localhost" + IdAustriaAuthConstants.ENDPOINT_METADATA,
+ authnRequest.getIssuer().getValue());
+
+ //check XML scheme
+ Saml2Utils.schemeValidation(authnRequest);
+
+ //check signature
+ final PvpSProfileRequest msg = new PvpSProfileRequest(
+ authnRequest,
+ SAMLConstants.SAML2_POST_BINDING_URI);
+ msg.setEntityID(authnRequest.getIssuer().getValue());
+ metadataProvider.addMetadataResolverIntoChain(
+ metadataFactory.createMetadataProvider(METADATA_SP_PATH, null, "jUnit SP", null));
+ samlVerifyEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider));
+
+ //check other elements
+ Assert.assertNotNull("Extensions", authnRequest.getExtensions());
+ Assert.assertFalse("No Requested attributes",
+ authnRequest.getExtensions().getUnknownXMLObjects().isEmpty());
+
+ Assert.assertEquals("#ReqAttributes", 1, authnRequest.getExtensions().getUnknownXMLObjects().size());
+ org.springframework.util.Assert.isInstanceOf(EaafRequestedAttributes.class,
+ authnRequest.getExtensions().getUnknownXMLObjects().get(0), "No Requested Attributes object");
+
+ return (EaafRequestedAttributes) authnRequest.getExtensions().getUnknownXMLObjects().get(0);
+
+ }
+
+ 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;
+
+ }
+
+ @Override
+ public boolean isWriteAsynch() {
+ return false;
+
+ }
+ };
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java
new file mode 100644
index 00000000..a0d6c988
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java
@@ -0,0 +1,413 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.utils;
+
+import org.apache.commons.lang3.RandomStringUtils;
+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;
+
+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 at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException;
+import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;
+import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ "/spring/SpringTest-context_lazy.xml"
+ })
+@DirtiesContext
+public class IdAustriaAuthCredentialProviderTest {
+
+ private static final String PATH_JKS = "pvp.jks";
+ private static final String ALIAS_METADATA = "metadata";
+ private static final String ALIAS_SIGN = "signing";
+ private static final String ALIAS_ENC = "encryption";
+ private static final String PASSWORD = "password";
+
+ @Autowired
+ private ApplicationContext context;
+ @Autowired
+ private MsConnectorDummyConfigMap config;
+
+ /**
+ * jUnit test initializer.
+ */
+ @Before
+ public void initialize() {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_PATH, PATH_JKS);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTOREPASSWORD, PASSWORD);
+
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_ALIAS);
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_PASSWORD);
+
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS);
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_PASSWORD);
+
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_ALIAS);
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD);
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void noKeyStoreUrl() {
+ config.removeConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_PATH);
+ try {
+ context.getBean(IdAustriaAuthCredentialProvider.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(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_PATH,
+ "src/test/resources/config/notExist.p12");
+ try {
+ context.getBean(IdAustriaAuthCredentialProvider.class);
+ Assert.fail("No KeyStore not detected");
+
+ } catch (final BeansException e) {
+ final Optional<Throwable> eaafException = FluentIterable.from(
+ Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(EaafConfigurationException.class)).first();
+ Assert.assertTrue("Wrong exception", eaafException.isPresent());
+ Assert.assertEquals("Wrong errorId", "internal.keystore.06",
+ ((EaafException) eaafException.get()).getErrorId());
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void noWrongKeyStorePassword() {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTOREPASSWORD, "test");
+ try {
+ context.getBean(IdAustriaAuthCredentialProvider.class);
+ Assert.fail("No KeyStore not detected");
+
+ } catch (final BeansException e) {
+ final Optional<Throwable> eaafException = FluentIterable.from(
+ Throwables.getCausalChain(e)).filter(
+ Predicates.instanceOf(EaafFactoryException.class)).first();
+ Assert.assertTrue("Wrong exception", eaafException.isPresent());
+ Assert.assertEquals("Wrong errorId", "internal.keystore.06",
+ ((EaafException) eaafException.get()).getErrorId());
+
+ }
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfigurationWrongAlias() {
+ final IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_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(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_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(IdAustriaAuthConstants.CONFIG_PROPS_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 IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_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(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_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(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD,
+ RandomStringUtils.randomAlphabetic(5));
+ 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 notKeyConfigurationValidAliasWrongPassword() {
+ final IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_ALIAS,
+ ALIAS_METADATA);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_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(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS,
+ ALIAS_SIGN);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_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(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_ALIAS,
+ ALIAS_ENC);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_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 IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ try {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_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(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_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(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_ALIAS,
+ RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_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 IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.class);
+
+ Assert.assertNotNull("Credetialprovider", credential);
+ Assert.assertNotNull("Friendlyname", credential.getFriendlyName());
+
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_ALIAS,
+ ALIAS_METADATA);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_METADATA_KEY_PASSWORD,
+ PASSWORD);
+ credential.getMetaDataSigningCredential();
+
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_ALIAS,
+ ALIAS_SIGN);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_SIGN_SIGNING_KEY_PASSWORD,
+ PASSWORD);
+ credential.getMessageSigningCredential();
+
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_ALIAS,
+ ALIAS_ENC);
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_ENCRYPTION_KEY_PASSWORD,
+ PASSWORD);
+ credential.getMessageEncryptionCredential();
+
+ }
+
+ @Test
+ @DirtiesContext
+ public void notKeyConfiguration() {
+ final IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.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 notKeyConfigurationPkcs12() {
+ config.putConfigValue(IdAustriaAuthConstants.CONFIG_PROPS_KEYSTORE_PATH, "pvp.p12");
+ final IdAustriaAuthCredentialProvider credential = context.getBean(
+ IdAustriaAuthCredentialProvider.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"));
+
+ }
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java
new file mode 100644
index 00000000..d9e73db1
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java
@@ -0,0 +1,236 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.utils;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.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.saml2.metadata.EntityDescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.w3c.dom.Element;
+
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+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.CredentialsNotAvailableException;
+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 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(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml" })
+public class IdAustriaAuthMetadataProviderFirstTest {
+
+ @Autowired IPvp2CredentialProvider credentialProvider;
+ @Autowired IdAustriaAuthMetadataProvider provider;
+ @Autowired PvpMetadataResolverFactory resolverFactory;
+ @Autowired MsConnectorDummyConfigMap config;
+
+ private static MockWebServer mockWebServer;
+ private static HttpUrl mockServerUrl;
+
+ /**
+ * 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");
+
+ }
+
+ /**
+ * jUnit test set-up.
+ *
+ * @throws ResolverException
+ *
+ */
+ @Before
+ public void testSetup() {
+ provider.fullyDestroy();
+
+ }
+
+ @Test
+ public void simpleManuelAddingTest() throws Pvp2MetadataException, ResolverException {
+ final IPvp2MetadataProvider resolver1 = resolverFactory.createMetadataProvider(
+ "classpath:/data/idp_metadata_sig_notvalid.xml",
+ null, "junit", null);
+ Assert.assertNotNull("Resolver 1 is null", resolver1);
+ provider.addMetadataResolverIntoChain(resolver1);
+
+ final IPvp2MetadataProvider resolver2 = resolverFactory.createMetadataProvider(
+ "classpath:/data/idp_metadata_sig_valid_wrong_alg.xml",
+ null, "junit", null);
+ Assert.assertNotNull("Resolver 2 is null", resolver2);
+ provider.addMetadataResolverIntoChain(resolver2);
+
+ final EntityDescriptor entity1 = provider.getEntityDescriptor("https://localEntity");
+ Assert.assertNotNull("Entity 1 not found", entity1);
+
+ final EntityDescriptor entity2 = provider.getEntityDescriptor(
+ "https://vidp.gv.at/ms_connector/pvp/metadata");
+ Assert.assertNotNull("Entity 2 not found", entity2);
+
+ final EntityDescriptor entity3 = provider.getEntityDescriptor("https://egiz.gv.at/abababa");
+ Assert.assertNull("Entity 3 found", entity3);
+
+ }
+
+ @Test
+ public void dynamicLoadingNoValidSignature() throws ResolverException {
+ final EntityDescriptor entity = provider.getEntityDescriptor("classpath:/data/idp_metadata_no_sig2.xml");
+ Assert.assertNull("Entity found", entity);
+
+ }
+
+ @Test
+ public void dynamicLoadingValidSignature() throws XMLParserException, UnmarshallingException,
+ SamlSigningException, CredentialsNotAvailableException, MarshallingException, ResolverException {
+
+ final String entityId = injectValidHttpMetadata();
+ final EntityDescriptor entity = provider.getEntityDescriptor(entityId);
+ Assert.assertNotNull("Entity not found", entity);
+
+ }
+
+ @Test
+ public void reloadNotPossible() throws XMLParserException, UnmarshallingException,
+ SamlSigningException, CredentialsNotAvailableException, MarshallingException, ResolverException {
+
+ final String entityId = injectValidHttpMetadata();
+ final EntityDescriptor entity = provider.getEntityDescriptor(entityId);
+ Assert.assertNotNull("Entity not found", entity);
+ Assert.assertNotNull("Entity not found",
+ provider.resolveSingle(generateEntityIdCreteria(entityId)));
+
+ Assert.assertFalse("Refresh should not be possible",
+ provider.refreshMetadataProvider(entityId));
+
+ final EntityDescriptor entity2 = provider.getEntityDescriptor(entityId);
+ Assert.assertNull("Entity not found", entity2);
+ Assert.assertNull("Entity not found",
+ provider.resolveSingle(generateEntityIdCreteria(entityId)));
+
+ Assert.assertFalse("Last refresh", provider.wasLastRefreshSuccess());
+
+ }
+
+ @Test
+ public void refeshTest() throws Pvp2MetadataException, ResolverException {
+ Assert.assertFalse("Last refresh", provider.wasLastRefreshSuccess());
+ Assert.assertNull("LastRefresh", provider.getLastRefresh());
+ Assert.assertNull("LastSuccessfulRefresh", provider.getLastSuccessfulRefresh());
+ Assert.assertNull("LastUpdate", provider.getLastUpdate());
+
+ final IPvp2MetadataProvider resolver1 = resolverFactory.createMetadataProvider(
+ "classpath:/data/idp_metadata_sig_notvalid.xml",
+ null, "junit", null);
+ Assert.assertNotNull("Resolver 1 is null", resolver1);
+ provider.addMetadataResolverIntoChain(resolver1);
+
+ final IPvp2MetadataProvider resolver2 = resolverFactory.createMetadataProvider(
+ "classpath:/data/idp_metadata_sig_valid_wrong_alg.xml",
+ null, "junit", null);
+ Assert.assertNotNull("Resolver 2 is null", resolver2);
+ provider.addMetadataResolverIntoChain(resolver2);
+
+ provider.refresh();
+
+ Assert.assertTrue("Last refresh", provider.wasLastRefreshSuccess());
+ Assert.assertNotNull("LastRefresh", provider.getLastRefresh());
+ Assert.assertNotNull("LastSuccessfulRefresh", provider.getLastSuccessfulRefresh());
+ Assert.assertNotNull("LastUpdate", provider.getLastUpdate());
+
+ }
+
+ @Test
+ public void reloadPossible() throws XMLParserException, UnmarshallingException,
+ SamlSigningException, CredentialsNotAvailableException, MarshallingException, ResolverException,
+ IOException {
+
+ mockWebServer.shutdown();
+ mockWebServer = new MockWebServer();
+ mockServerUrl = mockWebServer.url("/sp/metadata");
+
+ final String entityId = injectValidHttpMetadata();
+ final EntityDescriptor entity = provider.getEntityDescriptor(entityId);
+ Assert.assertNotNull("Entity not found", entity);
+ Assert.assertNotNull("Entity not found",
+ provider.resolveSingle(generateEntityIdCreteria(entityId)));
+
+ Assert.assertFalse("Last refresh", provider.wasLastRefreshSuccess());
+
+ injectValidHttpMetadata(entityId);
+ Assert.assertTrue("Refresh should not be possible",
+ provider.refreshMetadataProvider(entityId));
+
+ final EntityDescriptor entity2 = provider.getEntityDescriptor(entityId);
+ Assert.assertNotNull("Entity not found", entity2);
+ Assert.assertNotNull("Entity not found",
+ provider.resolveSingle(generateEntityIdCreteria(entityId)));
+
+ Assert.assertFalse("Last refresh", provider.wasLastRefreshSuccess());
+
+ }
+
+ private String injectValidHttpMetadata() throws SamlSigningException, CredentialsNotAvailableException,
+ XMLParserException, UnmarshallingException, MarshallingException {
+ return injectValidHttpMetadata(mockServerUrl.url().toString()
+ + "/" + RandomStringUtils.randomAlphabetic(5));
+ }
+
+ private String injectValidHttpMetadata(String dynEntityId) throws XMLParserException,
+ UnmarshallingException,
+ MarshallingException, SamlSigningException, CredentialsNotAvailableException {
+ final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream(
+ XMLObjectProviderRegistrySupport.getParserPool(),
+ IdAustriaAuthMetadataProviderFirstTest.class.getResourceAsStream("/data/idp_metadata_no_sig.xml"));
+ metadata.setValidUntil(Instant.now().plus(1, ChronoUnit.DAYS));
+ metadata.setSignature(null);
+ metadata.setEntityID(dynEntityId);
+ 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"));
+
+ return dynEntityId;
+
+ }
+
+ private CriteriaSet generateEntityIdCreteria(String entityId) {
+ final CriteriaSet result = new CriteriaSet();
+ result.add(new EntityIdCriterion(entityId));
+ return result;
+
+ }
+}
diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderSecondTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderSecondTest.java
new file mode 100644
index 00000000..9b3c1a34
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderSecondTest.java
@@ -0,0 +1,65 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.utils;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml" })
+public class IdAustriaAuthMetadataProviderSecondTest {
+
+ @Autowired
+ IdAustriaAuthMetadataProvider provider;
+
+ /**
+ * JUnit class initializer.
+ *
+ * @throws Exception In case of an OpenSAML3 initialization error
+ */
+ @BeforeClass
+ public static void classInitializer() throws Exception {
+ EaafOpenSaml3xInitializer.eaafInitialize();
+
+ }
+
+ /**
+ * jUnit test set-up.
+ *
+ * @throws ResolverException
+ *
+ */
+ @Before
+ public void testSetup() {
+ provider.fullyDestroy();
+
+ }
+
+ @Test
+ public void notTrustedX509CertsInTrustStore() throws ResolverException {
+ final EntityDescriptor entity = provider.getEntityDescriptor("classpath:/data/idp_metadata_no_sig2.xml");
+ Assert.assertNull("Entity found", entity);
+
+ }
+
+ @Test
+ public void readStaticInfos() {
+ Assert.assertEquals("wrong providerId",
+ IdAustriaAuthMetadataProvider.PROVIDER_ID, provider.getId());
+
+ provider.runGarbageCollector();
+
+ }
+
+}
diff --git a/modules/authmodule_id-austria/src/test/resources/config/junit.jks b/modules/authmodule_id-austria/src/test/resources/config/junit.jks
new file mode 100644
index 00000000..59e6ad13
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/config/junit.jks
Binary files differ
diff --git a/modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties b/modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties
new file mode 100644
index 00000000..66c13dbc
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties
@@ -0,0 +1,44 @@
+## HTTP-client defaults
+eidas.ms.client.http.connection.timeout.socket=1
+eidas.ms.client.http.connection.timeout.connection=1
+eidas.ms.client.http.connection.timeout.request=1
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
+# Additional requested attributes in SAML2 metadata
+#eidas.ms.modules.idaustriaauth.required.additional.attributes.1=
+#eidas.ms.modules.idaustriaauth.required.additional.attributes.2=
+#eidas.ms.modules.idaustriaauth.required.additional.attributes.3=
+#eidas.ms.modules.idaustriaauth.required.additional.attributes.4=
+
+
+
+## General PVP2 metadata configuration
+eidas.ms.pvp2.metadata.organisation.name=JUnit
+eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit
+eidas.ms.pvp2.metadata.organisation.url=http://junit.test
+eidas.ms.pvp2.metadata.contact.givenname=Max
+eidas.ms.pvp2.metadata.contact.surname=Mustermann
+eidas.ms.pvp2.metadata.contact.email=max@junit.test \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/test/resources/config/junit_test.jks b/modules/authmodule_id-austria/src/test/resources/config/junit_test.jks
new file mode 100644
index 00000000..ee6254a9
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/config/junit_test.jks
Binary files differ
diff --git a/modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks b/modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks
new file mode 100644
index 00000000..8fe3b03c
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks
Binary files differ
diff --git a/modules/authmodule_id-austria/src/test/resources/config/pvp.jks b/modules/authmodule_id-austria/src/test/resources/config/pvp.jks
new file mode 100644
index 00000000..f0a5a09a
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/config/pvp.jks
Binary files differ
diff --git a/modules/authmodule_id-austria/src/test/resources/config/pvp.p12 b/modules/authmodule_id-austria/src/test/resources/config/pvp.p12
new file mode 100644
index 00000000..183342f7
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/config/pvp.p12
Binary files differ
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml
new file mode 100644
index 00000000..8d3c1c66
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/high</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="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">AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml
new file mode 100644
index 00000000..ec4f451e
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/aabbcc</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="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">Heinz</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">Susi</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">1955-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">QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml
new file mode 100644
index 00000000..be8e7cc3
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <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="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">AT+CC:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.xml
new file mode 100644
index 00000000..6b86c6f1
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.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://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/aabbcc</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="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">Heinz</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">Susi</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">1955-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">AT+AB:QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="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:eidasid+AT+AB</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_jur.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_jur.xml
new file mode 100644
index 00000000..da97bbf4
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_jur.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/high</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="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">AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Generalvollmacht</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">999999m</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:baseid+XERSB</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Testfirma</saml2:AttributeValue>
+ </saml2:Attribute>
+
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_nat.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_nat.xml
new file mode 100644
index 00000000..8a84503d
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_mandate_nat.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/high</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="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">AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue>
+ </saml2:Attribute>
+
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">GeneralvollmachtBilateral</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT+XX:AFSDAFSDFDSFCSDAFASDF=</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Gerti</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Musterfrau</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">01-02-1941</saml2:AttributeValue>
+ </saml2:Attribute>
+
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml
new file mode 100644
index 00000000..cc534d09
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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="2035-03-05T06:44:51.017Z" Recipient="https://localhost/authhandler/sp/eidas/post"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2035-03-05T06:44:51.017Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute FriendlyName="piiTransactionId" Name="urn:eidgvat:attributes.piiTransactionId" 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">piiId_112233445566</saml2:AttributeValue>
+ </saml2:Attribute>
+ <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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/low</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">IT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" 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">aabbccddeeffgghh</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="userAuthBlock" Name="urn:eidgvat:attributes.authblock.signed" 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">MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml
new file mode 100644
index 00000000..2ae05ca1
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.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://localhost/demoapp/sp/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </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://localhost/authhandler/sp/idaustria/eidas/metadata</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/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml
new file mode 100644
index 00000000..0fd675e2
--- /dev/null
+++ b/modules/authmodule_id-austria/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://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</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://localhost/authhandler/sp/eidas/post"/>
+ </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://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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- 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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/high</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">IT</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/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml
new file mode 100644
index 00000000..ee5920dc
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</saml2:Issuer>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
+ <saml2p:StatusCode Value="9199"/>
+ </saml2p:StatusCode>
+ <saml2p:StatusMessage>Der Anmeldevorgang wurde durch den Benutzer abgebrochen.</saml2p:StatusMessage>
+ </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://localhost/authhandler/sp/eidas/post"/>
+ </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://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/low</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">IT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" 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">aabbccddeeffgghh</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="userConsent" Name="urn:eidgvat:attributes.consent.signed" 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">MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml
new file mode 100644
index 00000000..dd3f7908
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</saml2:Issuer>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
+ <saml2p:StatusCode Value=""/>
+ </saml2p:StatusCode>
+ <saml2p:StatusMessage>Der Anmeldevorgang wurde durch den Benutzer abgebrochen.</saml2p:StatusMessage>
+ </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://localhost/authhandler/sp/eidas/post"/>
+ </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://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/low</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">IT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" 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">aabbccddeeffgghh</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="userConsent" Name="urn:eidgvat:attributes.consent.signed" 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">MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml
new file mode 100644
index 00000000..1783cbab
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</saml2:Issuer>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
+ <saml2p:StatusCode Value="1005"/>
+ </saml2p:StatusCode>
+ <saml2p:StatusMessage>Der Anmeldevorgang wurde durch den Benutzer abgebrochen.</saml2p:StatusMessage>
+ </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://localhost/authhandler/sp/eidas/post"/>
+ </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://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/low</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">IT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" 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">aabbccddeeffgghh</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="userConsent" Name="urn:eidgvat:attributes.consent.signed" 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">MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml
new file mode 100644
index 00000000..1c7a8433
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/authhandler/sp/idaustria/eidas/post" 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">classpath:/data/idp_metadata_classpath_entity.xml</saml2:Issuer>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
+ </saml2p:StatusCode>
+ <saml2p:StatusMessage>Der Anmeldevorgang wurde durch den Benutzer abgebrochen.</saml2p:StatusMessage>
+ </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://localhost/authhandler/sp/eidas/post"/>
+ </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://localhost/authhandler/sp/idaustria/eidas/metadata</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>http://eidas.europa.eu/LoA/high</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="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:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://eidas.europa.eu/LoA/low</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">IT</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" 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">aabbccddeeffgghh</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute FriendlyName="userConsent" Name="urn:eidgvat:attributes.consent.signed" 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">MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt b/modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt
new file mode 100644
index 00000000..95843ea9
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAn0CBFtIcMwwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxMTAvBgNVBAMMKG5hdGlvbmFsIGNlbnRyYWwgZUlEQVMgbm9kZSAtIHRlc3RzeXN0ZW0wHhcN
+MTgwNzEzMDkyODQ0WhcNMjEwNDA3MDkyODQ0WjBPMQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJ
+WjExMC8GA1UEAwwobmF0aW9uYWwgY2VudHJhbCBlSURBUyBub2RlIC0gdGVzdHN5c3RlbTCCAaIw
+DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALK4bdf5OremKkj0+xCjU0eN7RUd1A2VqoGnvFUs
+t7xjLQ1PspHiDf9Pm2cwOIJabSnuZ01hYAGz9X+lU3Z3fwhVc+tEsuzsaAml/LPw3i3+ppoSTJDM
+iDvhCoUKTzJ8HBQj2gTvXNlqPljyGneuCJ+uBMr7Okq/XjMTJj2xzvutrHS3qIO+/w+OkY967QLV
+RXh0bdFqYqnyAnlYcWJPIwjanOJtE2difPYqers7ZW1F9djP0+IZRoyaook5rpLYvuQTHuvulgIE
+3zGlTuOx3sk8zMyInMndqi75Eh+ROnndSZE7gN3u5CfFpuO5pxFa2jj1h/AnR39Tg8/sU+Se+AwH
+rNvee3IWhxk5LkelYevfeCQos7Dv2ASE9XMCCs7FoE47w8fDalECh09MFKDiotpklbq3OrPg9NQ4
+D//k0GXlW5jYUKP/Wq/+suAI6mfhSnNkjOGMcMlzNTmwxGD/v7Py6OVA+YcJQsqYalLrqbvT2tXV
+mYBVO3oqafg+kfevfwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBgQCioM8k0EEBFtY4QyxOYFufPDLw
+9PNPct01ltnTVjNEEt/L6/8zYlDwrDeULEkJS7mV9zV3657NPQ5IPT/Ib93Uk/RPi0iOA2CGWIMa
+DQIODN3BUYr+zPUqhbKS6OWOhTgV8GiRCUbxrT1uc1AiacP63pga3TJX8k8WFnfW+Dqm2MfWWlxr
+4X2YB9VUW55X5sBNy035jYhEpp8NCK/fTAhoEQNCG+rm3T9qhT6YyOnbW2kXU747+ZwXT2qA5o4y
+a/9+6dDc+LUlHCEm4X7c6bcGvCfNezB4k56FzbAJlOLf2VDGzvEQBf0hsB+kElezm1VBlEkZ4Mjz
+pBpHBMoR21SwTpcvrbR4ig0Bk1eEHNK44sw0F32K5yww3gnJftMIZtPhjhk8UdG2/H6vs9s/to2V
+j4V6wN4o79RTULoQ8RjL6MPWEWzwOvOZXJAo2XJEECvDivSjIJvNC0lfrK3zI3LH3c1JR6q2EfeC
+Z50wTJMFoChSaqunJQXKo81g6wNhP00=
+-----END CERTIFICATE-----
diff --git a/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml
new file mode 100644
index 00000000..de565887
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor
+ xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
+ ID="_1a48ec3432f2f3ba6222724a5b06f873"
+ entityID="classpath:/data/idp_metadata_classpath_entity.xml"
+ validUntil="2045-02-06T08:47:26.211Z">
+ <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>MIIDMzCCAhsCBFtIcPowDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+ SVoxJDAiBgNVBAsMG2NlbnRyYWwgbmF0aW9uYWwgZUlEQVMgbm9kZTEaMBgGA1UEAwwRQXNzZXJ0
+ aW9uIHNpZ25pbmcwHhcNMTgwNzEzMDkyOTMwWhcNMjEwNDA3MDkyOTMwWjBeMQswCQYDVQQGEwJB
+ VDENMAsGA1UECgwERUdJWjEkMCIGA1UECwwbY2VudHJhbCBuYXRpb25hbCBlSURBUyBub2RlMRow
+ GAYDVQQDDBFBc3NlcnRpb24gc2lnbmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ AJ5zDYxMPRcz6AHaev1tS46Tq8sdgbGFM56uxk6c7LmMDC+HTzNX/3Q5S/YwSzgL3ue5TSw1ltOf
+ yMXMZ6D0+buWWcsxGEkQ8M3adKRFdQrEwafzwTA7pguq5WiHOkr4qwR7dLMome9z5cc3LRcwdOPP
+ gq7ahb5jM3hRqc5xkMWIuvql0NFXPzlHrjDLwy5nIWPOhL5abhVt4YsXbpbjXxFSGkDEAZ32K3EU
+ LNBr9FSUmJfbrVX9AU2T+BKIwiqXP8e/3UJHgPHQ0l5ljWp5P6u5+tvM21o8sUM4eArRa8BkdRsP
+ C92GVuASSUz2ZJ3JhAK1cSM8bnvaZVLQtTvPMAcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAp7z
+ TubWXW6YMpyLSvWBdZiiQ3X66XpSZLZJDIAkoPzEY0DSBp8I5YASIx4JTR5XJt+6MI9acgNIAYW8
+ DhtRwUMVaRWEtuCrfKhGLWm5KSxnhPcD3lzRZhY4ZcA7dUlirjf6hnqo2TFEmJ9fkM+rxwy1GkDD
+ 7j2YDSOFmSq9/Ud9/IbIfSnRu/lO0dh7iRrmg3y0Y/+plPxYmp4AHqehP11OchTz2FGGHVsSC2Vs
+ IVBQI6ANZYyOlicgfEEFHA06jP9OnA0EwEFr2P+di9caZg8vfibyzxMGeuf6CY0c0eLHokBCn2W8
+ vkzvWiER3pozRvCmXFjCVZfRjUunaJf2ow==
+ </ds:X509Certificate>
+ </ds:X509Data>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIC+DCCAeCgAwIBAgIEXh7TbTANBgkqhkiG9w0BAQsFADA+MQswCQYDVQQGEwJB
+ VDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxEDAOBgNVBAMMB3NpZ25p
+ bmcwHhcNMjAwMTE1MDg1NTA5WhcNMjkwMTE0MDg1NTA5WjA+MQswCQYDVQQGEwJB
+ VDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxEDAOBgNVBAMMB3NpZ25p
+ bmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUSiRjnDvPafZfhJ+L
+ 1wM86FKJX3VIAV/8TD9qJ6HOBkn5WwYfpheyCfRb6XVDyIGpO8qnMWAgC17Ngbmh
+ zj8d8HXNQ2l3uppMv24oUTfXyYhQfZWAghx0sTlRIx/ZmlnduJilx2S53Sa7ruJw
+ lQcBFXj9h9B8dtyegc86Sx6D9BumP1xU7+mEBk8Gv9rR5Khg0Y7qGfZWB0t4aikg
+ aupWveVwiGifOOSfR8czqIg9qUpMYfZiTEBTSRmN6sPiNWhd4J0GyAI9Rn5C9jz/
+ sSlQrxpN+4DXzsqSU5F6gzq3yRux6wyOzDlt2birf21VPQ9HIy4YCjZXwgDWG7AO
+ 821pAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADnwdaxUtQU6SIpYwIb2c0ljTmQi
+ 7ryUcUpNHtK0M0E5Mw5Ex8zwrWbNQZ2sUyc4r07M66iOIqHsYZUQlRYvVKHifDpA
+ r8TCgD7iGGdB3By8Ou0RaNW+03w1fwmi98CufbHCGvpv0o2KxlejoHZminNdQ79i
+ bN+01nhocezJQATEQlnwHLiQSjilXpZeLYDk8HbrcUXNRxezN4ChdH+uU54vf+Ux
+ qcj9QHcmBe1+BM8EXfqS1DbTwZl+NTCnh5OYl8fvIFSOHMBxwFrI4pyY0faxg9Uc
+ rCogn/oQ+mV1gnVUDaDhvvEnVGZQtrlt7heVId2BeNellVgsrcmdW8j4U9U=
+ </ds:X509Certificate>
+ </ds:X509Data>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDEN
+ MAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRh
+ MB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQx
+ DTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0
+ YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SY
+ O4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYI
+ KoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImn
+ AiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <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://vidp.gv.at/ms_connector/pvp/post" />
+ <md:SingleSignOnService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://vidp.gv.at/ms_connector/pvp/redirect" />
+ <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="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-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="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="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="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="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="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="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:EntityDescriptor>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml
new file mode 100644
index 00000000..bc55fe62
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_1a48ec3432f2f3ba6222724a5b06f873" entityID="https://vidp.gv.at/ms_connector/pvp/metadata" validUntil="2045-02-06T08:47:26.211Z">
+ <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>MIIDMzCCAhsCBFtIcPowDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxJDAiBgNVBAsMG2NlbnRyYWwgbmF0aW9uYWwgZUlEQVMgbm9kZTEaMBgGA1UEAwwRQXNzZXJ0
+aW9uIHNpZ25pbmcwHhcNMTgwNzEzMDkyOTMwWhcNMjEwNDA3MDkyOTMwWjBeMQswCQYDVQQGEwJB
+VDENMAsGA1UECgwERUdJWjEkMCIGA1UECwwbY2VudHJhbCBuYXRpb25hbCBlSURBUyBub2RlMRow
+GAYDVQQDDBFBc3NlcnRpb24gc2lnbmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJ5zDYxMPRcz6AHaev1tS46Tq8sdgbGFM56uxk6c7LmMDC+HTzNX/3Q5S/YwSzgL3ue5TSw1ltOf
+yMXMZ6D0+buWWcsxGEkQ8M3adKRFdQrEwafzwTA7pguq5WiHOkr4qwR7dLMome9z5cc3LRcwdOPP
+gq7ahb5jM3hRqc5xkMWIuvql0NFXPzlHrjDLwy5nIWPOhL5abhVt4YsXbpbjXxFSGkDEAZ32K3EU
+LNBr9FSUmJfbrVX9AU2T+BKIwiqXP8e/3UJHgPHQ0l5ljWp5P6u5+tvM21o8sUM4eArRa8BkdRsP
+C92GVuASSUz2ZJ3JhAK1cSM8bnvaZVLQtTvPMAcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAp7z
+TubWXW6YMpyLSvWBdZiiQ3X66XpSZLZJDIAkoPzEY0DSBp8I5YASIx4JTR5XJt+6MI9acgNIAYW8
+DhtRwUMVaRWEtuCrfKhGLWm5KSxnhPcD3lzRZhY4ZcA7dUlirjf6hnqo2TFEmJ9fkM+rxwy1GkDD
+7j2YDSOFmSq9/Ud9/IbIfSnRu/lO0dh7iRrmg3y0Y/+plPxYmp4AHqehP11OchTz2FGGHVsSC2Vs
+IVBQI6ANZYyOlicgfEEFHA06jP9OnA0EwEFr2P+di9caZg8vfibyzxMGeuf6CY0c0eLHokBCn2W8
+vkzvWiER3pozRvCmXFjCVZfRjUunaJf2ow==</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <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://vidp.gv.at/ms_connector/pvp/post"/>
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://vidp.gv.at/ms_connector/pvp/redirect"/>
+ <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="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-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="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="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="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="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="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="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:EntityDescriptor>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml
new file mode 100644
index 00000000..bdc176a0
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_1a48ec3432f2f3ba6222724a5b06f873" entityID="classpath:/data/idp_metadata_no_sig2.xml" validUntil="2045-02-06T08:47:26.211Z">
+ <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>MIIDMzCCAhsCBFtIcPowDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxJDAiBgNVBAsMG2NlbnRyYWwgbmF0aW9uYWwgZUlEQVMgbm9kZTEaMBgGA1UEAwwRQXNzZXJ0
+aW9uIHNpZ25pbmcwHhcNMTgwNzEzMDkyOTMwWhcNMjEwNDA3MDkyOTMwWjBeMQswCQYDVQQGEwJB
+VDENMAsGA1UECgwERUdJWjEkMCIGA1UECwwbY2VudHJhbCBuYXRpb25hbCBlSURBUyBub2RlMRow
+GAYDVQQDDBFBc3NlcnRpb24gc2lnbmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJ5zDYxMPRcz6AHaev1tS46Tq8sdgbGFM56uxk6c7LmMDC+HTzNX/3Q5S/YwSzgL3ue5TSw1ltOf
+yMXMZ6D0+buWWcsxGEkQ8M3adKRFdQrEwafzwTA7pguq5WiHOkr4qwR7dLMome9z5cc3LRcwdOPP
+gq7ahb5jM3hRqc5xkMWIuvql0NFXPzlHrjDLwy5nIWPOhL5abhVt4YsXbpbjXxFSGkDEAZ32K3EU
+LNBr9FSUmJfbrVX9AU2T+BKIwiqXP8e/3UJHgPHQ0l5ljWp5P6u5+tvM21o8sUM4eArRa8BkdRsP
+C92GVuASSUz2ZJ3JhAK1cSM8bnvaZVLQtTvPMAcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAp7z
+TubWXW6YMpyLSvWBdZiiQ3X66XpSZLZJDIAkoPzEY0DSBp8I5YASIx4JTR5XJt+6MI9acgNIAYW8
+DhtRwUMVaRWEtuCrfKhGLWm5KSxnhPcD3lzRZhY4ZcA7dUlirjf6hnqo2TFEmJ9fkM+rxwy1GkDD
+7j2YDSOFmSq9/Ud9/IbIfSnRu/lO0dh7iRrmg3y0Y/+plPxYmp4AHqehP11OchTz2FGGHVsSC2Vs
+IVBQI6ANZYyOlicgfEEFHA06jP9OnA0EwEFr2P+di9caZg8vfibyzxMGeuf6CY0c0eLHokBCn2W8
+vkzvWiER3pozRvCmXFjCVZfRjUunaJf2ow==</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <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://vidp.gv.at/ms_connector/pvp/post"/>
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://vidp.gv.at/ms_connector/pvp/redirect"/>
+ <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="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-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="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="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="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="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="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="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:EntityDescriptor>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml
new file mode 100644
index 00000000..86665a9c
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_1a48ec3432f2f3ba6222724a5b06f873" entityID="https://localEntity" validUntil="2045-02-06T08:47:26.211Z">
+ <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="#_1a48ec3432f2f3ba6222724a5b06f873">
+ <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>e6DiHa9scuvxJFBUipZ8PQcD4kAkmSIDZgZV+0/7glg=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>Czr2EwhK/0ZUZ5blQpJfNoOFEscLlxlmHPjmOJUIsxlB2pUn+ApULrjVpR1ViUcGZ0PVi2KChSNoSn09YKjtgPFBiSY010VYdaACgqluxUt6AwESObaqcyHVBzMDUr/g6jkRFEJV4vqnZQQDdDfTH4MXNqunORegS1saBHw4nJSOX4YfoVmIuT5uOlRrxvoG7srnGShvF7DmvIHBUBF5Tq9FyeSgwTM8udxl8Yl9FB2pREuR83CcbgjPrYKtzi6TiSfrWkcD0L5BvmMxN/BdaGDAorxYOnk41sWDJjrkY8C2SC1YDy6XT4SM06uFwstUrRn8QPg1hfbLHAyQNoaR8ecgapk5DkxmbATMcGY+SM4yQWkBdYT7GtufNmF8sIVaL6JOOTKAE9qqX/1N6N4zOPmm8rpIqVEQZtQ5usN/ubxbxLxUoTdDeo8RwkktW6zQ3Zv9+Iyf0DASYmK1IxN+fMw/qyeVy9r6o15ITHTqTmT/7BidKZ58m4HxIK52E3DU</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIEFTCCAn0CBFtIcMwwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxMTAvBgNVBAMMKG5hdGlvbmFsIGNlbnRyYWwgZUlEQVMgbm9kZSAtIHRlc3RzeXN0ZW0wHhcN
+MTgwNzEzMDkyODQ0WhcNMjEwNDA3MDkyODQ0WjBPMQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJ
+WjExMC8GA1UEAwwobmF0aW9uYWwgY2VudHJhbCBlSURBUyBub2RlIC0gdGVzdHN5c3RlbTCCAaIw
+DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALK4bdf5OremKkj0+xCjU0eN7RUd1A2VqoGnvFUs
+t7xjLQ1PspHiDf9Pm2cwOIJabSnuZ01hYAGz9X+lU3Z3fwhVc+tEsuzsaAml/LPw3i3+ppoSTJDM
+iDvhCoUKTzJ8HBQj2gTvXNlqPljyGneuCJ+uBMr7Okq/XjMTJj2xzvutrHS3qIO+/w+OkY967QLV
+RXh0bdFqYqnyAnlYcWJPIwjanOJtE2difPYqers7ZW1F9djP0+IZRoyaook5rpLYvuQTHuvulgIE
+3zGlTuOx3sk8zMyInMndqi75Eh+ROnndSZE7gN3u5CfFpuO5pxFa2jj1h/AnR39Tg8/sU+Se+AwH
+rNvee3IWhxk5LkelYevfeCQos7Dv2ASE9XMCCs7FoE47w8fDalECh09MFKDiotpklbq3OrPg9NQ4
+D//k0GXlW5jYUKP/Wq/+suAI6mfhSnNkjOGMcMlzNTmwxGD/v7Py6OVA+YcJQsqYalLrqbvT2tXV
+mYBVO3oqafg+kfevfwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBgQCioM8k0EEBFtY4QyxOYFufPDLw
+9PNPct01ltnTVjNEEt/L6/8zYlDwrDeULEkJS7mV9zV3657NPQ5IPT/Ib93Uk/RPi0iOA2CGWIMa
+DQIODN3BUYr+zPUqhbKS6OWOhTgV8GiRCUbxrT1uc1AiacP63pga3TJX8k8WFnfW+Dqm2MfWWlxr
+4X2YB9VUW55X5sBNy035jYhEpp8NCK/fTAhoEQNCG+rm3T9qhT6YyOnbW2kXU747+ZwXT2qA5o4y
+a/9+6dDc+LUlHCEm4X7c6bcGvCfNezB4k56FzbAJlOLf2VDGzvEQBf0hsB+kElezm1VBlEkZ4Mjz
+pBpHBMoR21SwTpcvrbR4ig0Bk1eEHNK44sw0F32K5yww3gnJftMIZtPhjhk8UdG2/H6vs9s/to2V
+j4V6wN4o79RTULoQ8RjL6MPWEWzwOvOZXJAo2XJEECvDivSjIJvNC0lfrK3zI3LH3c1JR6q2EfeC
+Z50wTJMFoChSaqunJQXKo81g6wNhP00=</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>MIIDMzCCAhsCBFtIcPowDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxJDAiBgNVBAsMG2NlbnRyYWwgbmF0aW9uYWwgZUlEQVMgbm9kZTEaMBgGA1UEAwwRQXNzZXJ0
+aW9uIHNpZ25pbmcwHhcNMTgwNzEzMDkyOTMwWhcNMjEwNDA3MDkyOTMwWjBeMQswCQYDVQQGEwJB
+VDENMAsGA1UECgwERUdJWjEkMCIGA1UECwwbY2VudHJhbCBuYXRpb25hbCBlSURBUyBub2RlMRow
+GAYDVQQDDBFBc3NlcnRpb24gc2lnbmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJ5zDYxMPRcz6AHaev1tS46Tq8sdgbGFM56uxk6c7LmMDC+HTzNX/3Q5S/YwSzgL3ue5TSw1ltOf
+yMXMZ6D0+buWWcsxGEkQ8M3adKRFdQrEwafzwTA7pguq5WiHOkr4qwR7dLMome9z5cc3LRcwdOPP
+gq7ahb5jM3hRqc5xkMWIuvql0NFXPzlHrjDLwy5nIWPOhL5abhVt4YsXbpbjXxFSGkDEAZ32K3EU
+LNBr9FSUmJfbrVX9AU2T+BKIwiqXP8e/3UJHgPHQ0l5ljWp5P6u5+tvM21o8sUM4eArRa8BkdRsP
+C92GVuASSUz2ZJ3JhAK1cSM8bnvaZVLQtTvPMAcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAp7z
+TubWXW6YMpyLSvWBdZiiQ3X66XpSZLZJDIAkoPzEY0DSBp8I5YASIx4JTR5XJt+6MI9acgNIAYW8
+DhtRwUMVaRWEtuCrfKhGLWm5KSxnhPcD3lzRZhY4ZcA7dUlirjf6hnqo2TFEmJ9fkM+rxwy1GkDD
+7j2YDSOFmSq9/Ud9/IbIfSnRu/lO0dh7iRrmg3y0Y/+plPxYmp4AHqehP11OchTz2FGGHVsSC2Vs
+IVBQI6ANZYyOlicgfEEFHA06jP9OnA0EwEFr2P+di9caZg8vfibyzxMGeuf6CY0c0eLHokBCn2W8
+vkzvWiER3pozRvCmXFjCVZfRjUunaJf2ow==</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <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://vidp.gv.at/ms_connector/pvp/post"/>
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://vidp.gv.at/ms_connector/pvp/redirect"/>
+ <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="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-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="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="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="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="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="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="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:EntityDescriptor>
diff --git a/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml
new file mode 100644
index 00000000..2187aa5f
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_1a48ec3432f2f3ba6222724a5b06f873" entityID="https://vidp.gv.at/ms_connector/pvp/metadata" validUntil="2045-02-06T08:47:26.211Z">
+ <dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="signature-1-1"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><dsig:Reference Id="reference-1-1" URI=""><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><dsig:DigestValue>dhkHkgZ1OOHG0nYWiRXrpZhIAx41103CG6DKDbBra8o=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue>AkxnEu9g3QgYC0JwuJXMYFrnNn6UMtrbtVn5YzkKBXxyYqZui4pEi/TRSM9r7Gt+
+4UqHrJVkYMbbuoO2kpiDnluPG+vHYzYFvF0agQ+gfGjpVQNRORN0FU7JPX+KPjpr
+sMU8wVZITSPU0GBBccvzrcpq7DQt0VbV5U7/Vq3KM/fop4ytAkUbTltUj/XxvAd1
+XdhB/zyeTTR2dafJ6Z2CKyM7MMmxwXYD1NrPGciPvTJ9ASHAT0lJM1dxrRNbeAja
+KTrNVj78MhSluRm5g7N1pMZzgMSpqN66AUg8pkSTvcRaNImPzYDcMQzHl2Tr362M
+RudjSgaEljK98TbBdgLFTg==</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIEqzCCBBSgAwIBAgIHANux81oNezANBgkqhkiG9w0BAQUFADBAMSIwIAYDVQQD
+ExlJQUlLIFRlc3QgSW50ZXJtZWRpYXRlIENBMQ0wCwYDVQQKEwRJQUlLMQswCQYD
+VQQGEwJBVDAeFw0xMzA5MjcwNTMzMzdaFw0yMzA5MjcwNTMzMzdaMIHkMQswCQYD
+VQQGEwJBVDENMAsGA1UEBxMER3JhejEmMCQGA1UEChMdR3JheiBVbml2ZXJzaXR5
+IG9mIFRlY2hub2xvZ3kxSDBGBgNVBAsTP0luc3RpdHV0ZSBmb3IgQXBwbGllZCBJ
+bmZvcm1hdGlvbiBQcm9jZXNzaW5nIGFuZCBDb21tdW5pY2F0aW9uczEUMBIGA1UE
+BBMLTU9BLVNTIFRlc3QxGDAWBgNVBCoTD0VHSVogVGVzdHBvcnRhbDEkMCIGA1UE
+AxMbRUdJWiBUZXN0cG9ydGFsIE1PQS1TUyBUZXN0MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAuDjOyf+mY+oQL2FQzzuaiC8C23vVKbq/n2Zi7BqSibZH
+mtqMJfmj4pT+hWSNHvVvWsaxFcx4KeNqdCMzwnw1r4P3Sf+2o5uFku5KHEMLMokR
+yYQG9VqY/KkB94ye7Pv6zT8gvKqxGFg96UamECep4swPaSZrA8AOER5WAtyGDzKI
+Tz+a5zfFaTXDoba7f98PCWR96yKiFjVOhzp38WVz4VJgz+b8ZSY7Xsv5Kn7DXjOL
+STX4MevFLki3rFPup3+4vGToaMBW3PEj67HXBdqR855Le6+E6rVxORqsXqlVwhsI
+6nuS0CO2LWYmBNR1IB0mXteeYH/HfxvuZc+7yDjdPQIDAQABo4IBhDCCAYAwDgYD
+VR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEmcH6VY4BG1EAGB
+TLoNR9vH/g6yMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9jcmxzL0lBSUtUZXN0X0ludGVybWVkaWF0ZUNBLmNybDCBqgYI
+KwYBBQUHAQEEgZ0wgZowSgYIKwYBBQUHMAGGPmh0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9PQ1NQP2NhPUlBSUtUZXN0X0ludGVybWVkaWF0ZUNBMEwGCCsG
+AQUFBzAChkBodHRwOi8vY2EuaWFpay50dWdyYXouYXQvY2Fwc28vY2VydHMvSUFJ
+S1Rlc3RfSW50ZXJtZWRpYXRlQ0EuY2VyMCEGA1UdEQQaMBiBFnRob21hcy5sZW56
+QGVnaXouZ3YuYXQwHwYDVR0jBBgwFoAUaKJeEdreL4BrRES/jfplNoEkp28wDQYJ
+KoZIhvcNAQEFBQADgYEAlFGjUxXLs7SAT8NtXSrv2WrjlklaRnHTFHLQwyVo8JWb
+gvRkHHDUv2o8ofXUY2R2WJ38dxeDoccgbXrJb/Qhi8IY7YhCwv/TuIZDisyAqo8W
+ORKSip/6HWlGCSR/Vgoet1GtCmF0FoUxFUIGSAuQ2yyt4fIzt5GJrU1X5ujjI1w=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo></dsig: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>MIIDMzCCAhsCBFtIcPowDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxJDAiBgNVBAsMG2NlbnRyYWwgbmF0aW9uYWwgZUlEQVMgbm9kZTEaMBgGA1UEAwwRQXNzZXJ0
+aW9uIHNpZ25pbmcwHhcNMTgwNzEzMDkyOTMwWhcNMjEwNDA3MDkyOTMwWjBeMQswCQYDVQQGEwJB
+VDENMAsGA1UECgwERUdJWjEkMCIGA1UECwwbY2VudHJhbCBuYXRpb25hbCBlSURBUyBub2RlMRow
+GAYDVQQDDBFBc3NlcnRpb24gc2lnbmluZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJ5zDYxMPRcz6AHaev1tS46Tq8sdgbGFM56uxk6c7LmMDC+HTzNX/3Q5S/YwSzgL3ue5TSw1ltOf
+yMXMZ6D0+buWWcsxGEkQ8M3adKRFdQrEwafzwTA7pguq5WiHOkr4qwR7dLMome9z5cc3LRcwdOPP
+gq7ahb5jM3hRqc5xkMWIuvql0NFXPzlHrjDLwy5nIWPOhL5abhVt4YsXbpbjXxFSGkDEAZ32K3EU
+LNBr9FSUmJfbrVX9AU2T+BKIwiqXP8e/3UJHgPHQ0l5ljWp5P6u5+tvM21o8sUM4eArRa8BkdRsP
+C92GVuASSUz2ZJ3JhAK1cSM8bnvaZVLQtTvPMAcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAp7z
+TubWXW6YMpyLSvWBdZiiQ3X66XpSZLZJDIAkoPzEY0DSBp8I5YASIx4JTR5XJt+6MI9acgNIAYW8
+DhtRwUMVaRWEtuCrfKhGLWm5KSxnhPcD3lzRZhY4ZcA7dUlirjf6hnqo2TFEmJ9fkM+rxwy1GkDD
+7j2YDSOFmSq9/Ud9/IbIfSnRu/lO0dh7iRrmg3y0Y/+plPxYmp4AHqehP11OchTz2FGGHVsSC2Vs
+IVBQI6ANZYyOlicgfEEFHA06jP9OnA0EwEFr2P+di9caZg8vfibyzxMGeuf6CY0c0eLHokBCn2W8
+vkzvWiER3pozRvCmXFjCVZfRjUunaJf2ow==</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <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://vidp.gv.at/ms_connector/pvp/post"/>
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://vidp.gv.at/ms_connector/pvp/redirect"/>
+ <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="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-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="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="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="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="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="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="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:EntityDescriptor> \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt b/modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt
new file mode 100644
index 00000000..35831d03
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDEN
+MAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRh
+MB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQx
+DTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0
+YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SY
+O4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYI
+KoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImn
+AiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA==
+-----END CERTIFICATE-----
+
diff --git a/modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt b/modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt
new file mode 100644
index 00000000..35a82125
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+DCCAeCgAwIBAgIEXh7TbTANBgkqhkiG9w0BAQsFADA+MQswCQYDVQQGEwJB
+VDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxEDAOBgNVBAMMB3NpZ25p
+bmcwHhcNMjAwMTE1MDg1NTA5WhcNMjkwMTE0MDg1NTA5WjA+MQswCQYDVQQGEwJB
+VDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxEDAOBgNVBAMMB3NpZ25p
+bmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUSiRjnDvPafZfhJ+L
+1wM86FKJX3VIAV/8TD9qJ6HOBkn5WwYfpheyCfRb6XVDyIGpO8qnMWAgC17Ngbmh
+zj8d8HXNQ2l3uppMv24oUTfXyYhQfZWAghx0sTlRIx/ZmlnduJilx2S53Sa7ruJw
+lQcBFXj9h9B8dtyegc86Sx6D9BumP1xU7+mEBk8Gv9rR5Khg0Y7qGfZWB0t4aikg
+aupWveVwiGifOOSfR8czqIg9qUpMYfZiTEBTSRmN6sPiNWhd4J0GyAI9Rn5C9jz/
+sSlQrxpN+4DXzsqSU5F6gzq3yRux6wyOzDlt2birf21VPQ9HIy4YCjZXwgDWG7AO
+821pAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADnwdaxUtQU6SIpYwIb2c0ljTmQi
+7ryUcUpNHtK0M0E5Mw5Ex8zwrWbNQZ2sUyc4r07M66iOIqHsYZUQlRYvVKHifDpA
+r8TCgD7iGGdB3By8Ou0RaNW+03w1fwmi98CufbHCGvpv0o2KxlejoHZminNdQ79i
+bN+01nhocezJQATEQlnwHLiQSjilXpZeLYDk8HbrcUXNRxezN4ChdH+uU54vf+Ux
+qcj9QHcmBe1+BM8EXfqS1DbTwZl+NTCnh5OYl8fvIFSOHMBxwFrI4pyY0faxg9Uc
+rCogn/oQ+mV1gnVUDaDhvvEnVGZQtrlt7heVId2BeNellVgsrcmdW8j4U9U=
+-----END CERTIFICATE-----
diff --git a/modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt b/modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt
new file mode 100644
index 00000000..fda99f2b
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEqzCCBBSgAwIBAgIHANux81oNezANBgkqhkiG9w0BAQUFADBAMSIwIAYDVQQD
+ExlJQUlLIFRlc3QgSW50ZXJtZWRpYXRlIENBMQ0wCwYDVQQKEwRJQUlLMQswCQYD
+VQQGEwJBVDAeFw0xMzA5MjcwNTMzMzdaFw0yMzA5MjcwNTMzMzdaMIHkMQswCQYD
+VQQGEwJBVDENMAsGA1UEBxMER3JhejEmMCQGA1UEChMdR3JheiBVbml2ZXJzaXR5
+IG9mIFRlY2hub2xvZ3kxSDBGBgNVBAsTP0luc3RpdHV0ZSBmb3IgQXBwbGllZCBJ
+bmZvcm1hdGlvbiBQcm9jZXNzaW5nIGFuZCBDb21tdW5pY2F0aW9uczEUMBIGA1UE
+BBMLTU9BLVNTIFRlc3QxGDAWBgNVBCoTD0VHSVogVGVzdHBvcnRhbDEkMCIGA1UE
+AxMbRUdJWiBUZXN0cG9ydGFsIE1PQS1TUyBUZXN0MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAuDjOyf+mY+oQL2FQzzuaiC8C23vVKbq/n2Zi7BqSibZH
+mtqMJfmj4pT+hWSNHvVvWsaxFcx4KeNqdCMzwnw1r4P3Sf+2o5uFku5KHEMLMokR
+yYQG9VqY/KkB94ye7Pv6zT8gvKqxGFg96UamECep4swPaSZrA8AOER5WAtyGDzKI
+Tz+a5zfFaTXDoba7f98PCWR96yKiFjVOhzp38WVz4VJgz+b8ZSY7Xsv5Kn7DXjOL
+STX4MevFLki3rFPup3+4vGToaMBW3PEj67HXBdqR855Le6+E6rVxORqsXqlVwhsI
+6nuS0CO2LWYmBNR1IB0mXteeYH/HfxvuZc+7yDjdPQIDAQABo4IBhDCCAYAwDgYD
+VR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEmcH6VY4BG1EAGB
+TLoNR9vH/g6yMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9jcmxzL0lBSUtUZXN0X0ludGVybWVkaWF0ZUNBLmNybDCBqgYI
+KwYBBQUHAQEEgZ0wgZowSgYIKwYBBQUHMAGGPmh0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9PQ1NQP2NhPUlBSUtUZXN0X0ludGVybWVkaWF0ZUNBMEwGCCsG
+AQUFBzAChkBodHRwOi8vY2EuaWFpay50dWdyYXouYXQvY2Fwc28vY2VydHMvSUFJ
+S1Rlc3RfSW50ZXJtZWRpYXRlQ0EuY2VyMCEGA1UdEQQaMBiBFnRob21hcy5sZW56
+QGVnaXouZ3YuYXQwHwYDVR0jBBgwFoAUaKJeEdreL4BrRES/jfplNoEkp28wDQYJ
+KoZIhvcNAQEFBQADgYEAlFGjUxXLs7SAT8NtXSrv2WrjlklaRnHTFHLQwyVo8JWb
+gvRkHHDUv2o8ofXUY2R2WJ38dxeDoccgbXrJb/Qhi8IY7YhCwv/TuIZDisyAqo8W
+ORKSip/6HWlGCSR/Vgoet1GtCmF0FoUxFUIGSAuQ2yyt4fIzt5GJrU1X5ujjI1w=
+-----END CERTIFICATE-----
diff --git a/modules/authmodule_id-austria/src/test/resources/data/pvp_postbinding_template.html b/modules/authmodule_id-austria/src/test/resources/data/pvp_postbinding_template.html
new file mode 100644
index 00000000..5c65e25a
--- /dev/null
+++ b/modules/authmodule_id-austria/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/modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml b/modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml
new file mode 100644
index 00000000..32e90604
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_1a48ec3432f2f3ba6222724a5b06f873" entityID="http://localhost/sp/idaustria/eidas/metadata" validUntil="2045-02-06T08:47:26.211Z">
+ <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+DCCAeCgAwIBAgIEXh7TbTANBgkqhkiG9w0BAQsFADA+MQswCQYDVQQGEwJBVDENMAsGA1UE
+CgwERUdJWjEOMAwGA1UECwwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcwHhcNMjAwMTE1MDg1NTA5
+WhcNMjkwMTE0MDg1NTA5WjA+MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwF
+alVuaXQxEDAOBgNVBAMMB3NpZ25pbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCU
+SiRjnDvPafZfhJ+L1wM86FKJX3VIAV/8TD9qJ6HOBkn5WwYfpheyCfRb6XVDyIGpO8qnMWAgC17N
+gbmhzj8d8HXNQ2l3uppMv24oUTfXyYhQfZWAghx0sTlRIx/ZmlnduJilx2S53Sa7ruJwlQcBFXj9
+h9B8dtyegc86Sx6D9BumP1xU7+mEBk8Gv9rR5Khg0Y7qGfZWB0t4aikgaupWveVwiGifOOSfR8cz
+qIg9qUpMYfZiTEBTSRmN6sPiNWhd4J0GyAI9Rn5C9jz/sSlQrxpN+4DXzsqSU5F6gzq3yRux6wyO
+zDlt2birf21VPQ9HIy4YCjZXwgDWG7AO821pAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADnwdaxU
+tQU6SIpYwIb2c0ljTmQi7ryUcUpNHtK0M0E5Mw5Ex8zwrWbNQZ2sUyc4r07M66iOIqHsYZUQlRYv
+VKHifDpAr8TCgD7iGGdB3By8Ou0RaNW+03w1fwmi98CufbHCGvpv0o2KxlejoHZminNdQ79ibN+0
+1nhocezJQATEQlnwHLiQSjilXpZeLYDk8HbrcUXNRxezN4ChdH+uU54vf+Uxqcj9QHcmBe1+BM8E
+XfqS1DbTwZl+NTCnh5OYl8fvIFSOHMBxwFrI4pyY0faxg9UcrCogn/oQ+mV1gnVUDaDhvvEnVGZQ
+trlt7heVId2BeNellVgsrcmdW8j4U9U=</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:EntityDescriptor>
diff --git a/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml b/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml
new file mode 100644
index 00000000..fe9ff441
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_mapConfig.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">
+
+ <context:annotation-config />
+
+ <bean id="dummyMapBasedConfiguration"
+ class="at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap">
+ <constructor-arg value="/config/junit_config_1.properties" />
+ <property name="configRootDirSufix" value="src/test/resources/config" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml b/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml
new file mode 100644
index 00000000..99778839
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml
@@ -0,0 +1,32 @@
+<?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:/SpringTest-context_authManager.xml" />
+ <import resource="classpath:/eaaf_pvp.beans.xml" />
+ <import resource="classpath:/spring/id_austria_auth.beans.xml" />
+ <import resource="classpath:/spring/id_austria_task.beans.xml" />
+ <import resource="classpath:/eaaf_pvp_sp.beans.xml" />
+
+ <bean id="dummyPvpConfig"
+ class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpConfiguration" />
+
+ <bean id="dummyGuiConfigFactory"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" />
+
+ <bean id="dummyVelocityBuilder"
+ class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" />
+
+ <bean id="FinalizeAuthenticationTask"
+ class="at.gv.egiz.eaaf.core.impl.idp.controller.tasks.FinalizeAuthenticationTask"
+ scope="prototype" />
+
+</beans> \ No newline at end of file
diff --git a/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml b/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml
new file mode 100644
index 00000000..5360960b
--- /dev/null
+++ b/modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml
@@ -0,0 +1,24 @@
+<?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 />
+
+ <import resource="classpath:/spring/eaaf_utils.beans.xml"/>
+
+ <bean id="idAustriaAuthCredentialProvider"
+ class="at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider"
+ lazy-init="true" />
+
+ <bean id="dummyPvpConfig"
+ class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpConfiguration"
+ lazy-init="true" />
+
+</beans>
diff --git a/modules/core_common_lib/checks/spotbugs-exclude.xml b/modules/core_common_lib/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..9700a0c0
--- /dev/null
+++ b/modules/core_common_lib/checks/spotbugs-exclude.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+ <Match>
+ <!-- View parameters are hard-coded values -->
+ <Class name="at.asitplus.eidas.specific.connector.gui.SpringMvcGuiFormBuilderImpl" />
+ <Method name="build" />
+ <Bug pattern="SPRING_FILE_DISCLOSURE" />
+ </Match>
+ <Match>
+ <!-- Builder pattern does not expose date elements -->
+ <OR>
+ <Class name="at.asitplus.eidas.specific.connector.config.ServiceProviderConfiguration" />
+ <Class name="at.asitplus.eidas.specific.connector.gui.StaticGuiBuilderConfiguration"/>
+ </OR>
+ <OR>
+ <Bug pattern="EI_EXPOSE_REP" />
+ <Bug pattern="EI_EXPOSE_REP2" />
+ </OR>
+ </Match>
+</FindBugsFilter>
diff --git a/modules/core_common_lib/pom.xml b/modules/core_common_lib/pom.xml
new file mode 100644
index 00000000..a27c20e3
--- /dev/null
+++ b/modules/core_common_lib/pom.xml
@@ -0,0 +1,106 @@
+<?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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>core_common_lib</artifactId>
+ <name>ms_specific_common_lib</name>
+ <packaging>jar</packaging>
+
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- jUnit test dependencies -->
+ <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>
+
+ </dependencies>
+
+ <build>
+ <finalName>core_common_lib</finalName>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+
+ <!-- enable co-existence of testng and junit -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs-maven-plugin</artifactId>
+ <version>${spotbugs-maven-plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsConnectorEventCodes.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsConnectorEventCodes.java
new file mode 100644
index 00000000..d15cf77c
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsConnectorEventCodes.java
@@ -0,0 +1,52 @@
+/*
+ * 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.asitplus.eidas.specific.core;
+
+public class MsConnectorEventCodes {
+
+ public static final int STARTING_COUNTRY_SELECTION = 4100;
+ public static final int COUNTRY_SELECTED = 4101;
+
+ public static final int PROCESS_STOPPED_BY_USER = 4102;
+
+ public static final int EIDAS_NODE_CONNECTED = 6101;
+ public static final int RESPONSE_FROM_EIDAS_NODE = 6102;
+ public static final int RESPONSE_FROM_EIDAS_NODE_VALID = 6103;
+ public static final int RESPONSE_FROM_EIDAS_NODE_NOT_VALID = 6104;
+ public static final int RESPONSE_FROM_EIDAS_MDSDATA = 6105;
+
+ public static final int SZR_IDL_RECEIVED = 6200;
+ public static final int SZR_BPK_RECEIVED = 6201;
+ public static final int SZR_VSZ_RECEIVED = 6202;
+ public static final int SZR_EIDASBIND_RECEIVED = 6203;
+ public static final int TECH_AUCHBLOCK_CREATED = 6204;
+
+ public static final int SZR_ERNB_EIDAS_RAW_ID = 6210;
+ public static final int SZR_ERNB_EIDAS_ERNB_ID = 6211;
+
+
+ private MsConnectorEventCodes() {
+ // hidden constructor for class with static values only.
+ }
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java
new file mode 100644
index 00000000..ecf5cf67
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java
@@ -0,0 +1,229 @@
+/*
+ * 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.asitplus.eidas.specific.core;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder;
+
+public class MsEidasNodeConstants {
+ // ************ configuration properties ************
+ public static final String PROP_CONFIG_APPLICATION_PREFIX = "eidas.ms.";
+ public static final String PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX = "context.url.prefix";
+ public static final String PROP_CONFIG_APPLICATION_PUBLIC_URL_REQUEST_VALIDATION =
+ "context.url.request.validation";
+ public static final String PROP_CONFIG_REVISIONLOG_LOG_IP_ADDRESS_OF_USER =
+ "revisionlog.logIPAddressOfUser";
+ public static final String PROP_CONFIG_REVISIONLOG_WRITE_MDS_INTO_REVISION_LOG =
+ "revisionlog.write.MDS.into.revisionlog";
+ public static final String PROP_CONFIG_TECHNICALLOG_WRITE_MDS_INTO_TECH_LOG =
+ "technicallog.write.MDS.into.techlog";
+
+ public static final String PROP_CONFIG_WEBCONTENT_STATIC_PATH = "webcontent.static.directory";
+ public static final String PROP_CONFIG_WEBCONTENT_PROPERTIES_PATH = "webcontent.properties";
+ public static final String PROP_CONFIG_WEBCONTENT_TEMPLATES_PATH = "webcontent.templates";
+
+ public static final String PROP_CONFIG_WEBCONTENT_TEMPLATES_CCSELECTION = "webcontent.templates.countryselection";
+
+ public static final String PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL =
+ "monitoring.eIDASNode.metadata.url";
+
+ private static final String PROP_CONFIG_PVP2_PREFIX = "pvp2.";
+ public static final String CONFIG_PROPS_KEYSTORE_TYPE = PROP_CONFIG_PVP2_PREFIX + "keystore.type";
+ public static final String CONFIG_PROPS_KEYSTORE_NAME = PROP_CONFIG_PVP2_PREFIX + "keystore.name";
+ public static final String PROP_CONFIG_PVP2_KEYSTORE_PATH = PROP_CONFIG_PVP2_PREFIX + "keystore.path";
+ public static final String PROP_CONFIG_PVP2_KEYSTORE_PASSWORD = PROP_CONFIG_PVP2_PREFIX
+ + "keystore.password";
+ public static final String PROP_CONFIG_PVP2_KEY_METADATA_ALIAS = PROP_CONFIG_PVP2_PREFIX
+ + "key.metadata.alias";
+ public static final String PROP_CONFIG_PVP2_KEY_METADATA_PASSWORD = PROP_CONFIG_PVP2_PREFIX
+ + "key.metadata.password";
+ public static final String PROP_CONFIG_PVP2_KEY_SIGNING_ALIAS = PROP_CONFIG_PVP2_PREFIX
+ + "key.signing.alias";
+ public static final String PROP_CONFIG_PVP2_KEY_SIGNING_PASSWORD = PROP_CONFIG_PVP2_PREFIX
+ + "key.signing.password";
+ public static final String PROP_CONFIG_PVP2_METADATA_VALIDITY = PROP_CONFIG_PVP2_PREFIX
+ + "metadata.validity";
+
+ public static final String CONFIG_PROPS_METADATA_CONTACT_GIVENNAME =
+ PROP_CONFIG_PVP2_PREFIX + "metadata.contact.givenname";
+ public static final String CONFIG_PROPS_METADATA_CONTACT_SURNAME =
+ PROP_CONFIG_PVP2_PREFIX + "metadata.contact.surname";
+ public static final String CONFIG_PROPS_METADATA_CONTACT_EMAIL =
+ PROP_CONFIG_PVP2_PREFIX + "metadata.contact.email";
+ public static final String CONFIG_PROPS_METADATA_ORGANISATION_NAME =
+ PROP_CONFIG_PVP2_PREFIX + "metadata.organisation.name";
+ public static final String CONFIG_PROPS_METADATA_ORGANISATION_FRIENDLYNAME =
+ PROP_CONFIG_PVP2_PREFIX + "metadata.organisation.friendyname";
+ public static final String CONFIG_PROPS_METADATA_ORGANISATION_URL =
+ PROP_CONFIG_PVP2_PREFIX + "metadata.organisation.url";
+
+ // TODO: is not implemented yet
+ public static final String PROP_CONFIG_SP_VALIDATION_DISABLED =
+ "configuration.sp.disableRegistrationRequirement";
+
+ public static final String PROP_EIDAS_REQUEST_LOA_MINIMUM_LEVEL =
+ "auth.eIDAS.node_v2.loa.requested.minimum";
+
+ public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE =
+ "auth.eIDAS.authblock.keystore.type";
+ public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH =
+ "auth.eIDAS.authblock.keystore.path";
+ public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD =
+ "auth.eIDAS.authblock.keystore.password";
+ public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME =
+ "auth.eIDAS.authblock.keystore.name";
+ public static final String PROP_CONFIG_AUTHBLOCK_KEY_ALIAS =
+ "auth.eIDAS.authblock.key.alias";
+ public static final String PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD =
+ "auth.eIDAS.authblock.key.password";
+
+
+
+
+ public static final String PROP_CONFIG_SP_LIST_PREFIX = "sp";
+ public static final String PROP_CONFIG_SP_UNIQUEIDENTIFIER = EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER;
+ public static final String PROP_CONFIG_SP_FRIENDLYNAME = "friendlyName";
+ public static final String PROP_CONFIG_SP_PVP2_METADATA_URL = "pvp2.metadata.url";
+ public static final String PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE = "pvp2.metadata.truststore";
+ public static final String PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE_PASSWORD =
+ "pvp2.metadata.truststore.password";
+ public static final String PROP_CONFIG_SP_NEW_EID_MODE =
+ "newEidMode";
+
+ public static final String PROP_CONFIG_SP_POLICY_ALLOWED_TARGETS = "policy.allowed.requested.targets";
+ public static final String PROP_CONFIG_SP_POLICY_BASEIDTRANSFER_RESTRICTION =
+ "policy.hasBaseIdTransferRestriction";
+
+ public static final String PROP_CONFIG_PVP_SCHEME_VALIDATION = "configuration.pvp.scheme.validation";
+ public static final String PROP_CONFIG_PVP_ENABLE_ENTITYCATEGORIES =
+ "configuration.pvp.enable.entitycategories";
+
+ // ********** default values ***************
+
+ // Default policy for SP-targets requested by MOA-ID to ms-specific eIDAS
+ // Connector
+ public static final String POLICY_DEFAULT_ALLOWED_TARGETS = ".*";
+ // EAAFConstants.URN_PREFIX_CDID.replaceAll("\\.", "\\\\.").replaceAll("\\+",
+ // "\\\\+") + ".*";
+
+ public static final int METADATA_SOCKED_TIMEOUT = 20 * 1000; // 20 seconds metadata socked timeout
+ public static final int DEFAULT_PVP_METADATA_VALIDITY = 24; // 24 hours
+ public static final int DEFAULT_PVP_ASSERTION_VALIDITY = 5; // 5 minutes
+
+ // ************ application end-points *************
+ public static final String ENDPOINT_PVP_METADATA = "/pvp/metadata";
+ public static final String ENDPOINT_PVP_POST = "/pvp/post";
+ public static final String ENDPOINT_PVP_REDIRECT = "/pvp/redirect";
+
+ public static final String ENDPOINT_COUNTRYSELECTION = "/myHomeCountry";
+
+ public static final String ENDPOINT_MONITORING_MONITOR = "/monitoring";
+ public static final String ENDPOINT_MONITORING_VERIFY = "/verify";
+
+ // ************ paths and templates ************
+ public static final String CLASSPATH_TEMPLATE_DIR = "/templates/";
+ public static final String FILESYSTEM_TEMPLATE_DIR = "./templates/";
+
+ public static final String TEMPLATE_HTML_ERROR = "error_message.html";
+ public static final String TEMPLATE_HTML_PVP_POSTBINDING = "pvp2_post_binding.html";
+ public static final String TEMPLATE_HTML_COUNTRYSELECTION = "countrySelection.html";
+
+ // ************ execution context and generic data ************
+ public static final String REQ_PARAM_SELECTED_COUNTRY = "selectedCountry";
+ public static final String REQ_PARAM_SELECTED_ENVIRONMENT = "selectedEnvironment";
+ public static final String REQ_PARAM_STOP_PROCESS = "stopAuthProcess";
+
+ public static final String REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_PRODUCTION = "prod";
+ public static final String REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_QS = "qs";
+ public static final String REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_TESTING = "test";
+ public static final String REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_DEVELOPMENT = "dev";
+
+ public static final String DATA_REQUESTERID = "req_requesterId";
+ public static final String DATA_PROVIDERNAME = "req_providerName";
+ public static final String DATA_REQUESTED_LOA_LIST = "req_requestedLoA";
+ public static final String DATA_REQUESTED_LOA_COMPERISON = "req_requestedLoAComperision";
+
+ public static final List<String> COUNTRY_SELECTION_PARAM_WHITELIST =
+ Arrays.asList(REQ_PARAM_SELECTED_COUNTRY, REQ_PARAM_SELECTED_ENVIRONMENT);
+
+
+ public static final String EID_BINDING_PUBLIC_KEY_NAME = "urn:eidgvat:attributes.binding.pubkey";
+
+
+ // ---- Attribute configuration ------
+ public static final String ATTR_EIDAS_PERSONAL_IDENTIFIER =
+ AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER + PvpAttributeDefinitions.BPK_NAME;
+ public static final String ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER =
+ AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME;
+ public static final String ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER =
+ AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER
+ + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME;
+
+ public static final String AUTH_DATA_SZR_AUTHBLOCK = "authData_AUTHBLOCK";
+ public static final String AUTH_DATA_EIDAS_BIND = "authData_EIDAS_BIND";
+
+
+ public static final List<Triple<String, String, Boolean>> DEFAULT_REQUIRED_MANDATE_NAT_PVP_ATTRIBUTES =
+ Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME,
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME,
+ PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME,
+ PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME,
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, false));
+
+ }
+ });
+
+ public static final List<Triple<String, String, Boolean>> DEFAULT_REQUIRED_MANDATE_JUR_PVP_ATTRIBUTES =
+ Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME,
+ PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, false));
+ add(Triple.newInstance(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME,
+ PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, false));
+
+ }
+ });
+
+
+ private MsEidasNodeConstants() {
+ //hidden Constructor for class with static values only.
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/BasicConfigurationProvider.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/BasicConfigurationProvider.java
new file mode 100644
index 00000000..3a1bdc9c
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/BasicConfigurationProvider.java
@@ -0,0 +1,155 @@
+/*
+ * 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.asitplus.eidas.specific.core.config;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.conf.AbstractConfigurationImpl;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+
+@Service("BasicMSSpecificNodeConfig")
+@Profile("deprecatedConfig")
+public class BasicConfigurationProvider extends AbstractConfigurationImpl {
+ private static final Logger log = LoggerFactory.getLogger(BasicConfigurationProvider.class);
+
+ private final Map<String, ISpConfiguration> spConfigCache = new HashMap<>();
+
+ public BasicConfigurationProvider(String configPath) throws EaafConfigurationException {
+ super(configPath);
+
+ }
+
+ @Override
+ public ISpConfiguration getServiceProviderConfiguration(String entityId) throws EaafConfigurationException {
+ if (!spConfigCache.containsKey(entityId)) {
+ log.debug("SP: " + entityId + " is NOT cached. Starting load operation ... ");
+ final Map<String, String> allSPs = getBasicConfigurationWithPrefix(
+ MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX + KeyValueUtils.KEY_DELIMITER);
+ for (Entry<String, String> entry : allSPs.entrySet()) {
+ if (entry.getKey().endsWith(MsEidasNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER)
+ && entry.getValue().equals(entityId)) {
+ final String listId = KeyValueUtils.getParentKey(entry.getKey());
+ log.trace("Find SP configuration with list-Id: " + listId
+ + ". Extracting configuration elements ... ");
+ final Map<String, String> spConfig = KeyValueUtils.getSubSetWithPrefix(allSPs, listId
+ + KeyValueUtils.KEY_DELIMITER);
+ spConfigCache.put(entityId,
+ new ServiceProviderConfiguration(spConfig, this));
+ break;
+ }
+ }
+
+ if (spConfigCache.containsKey(entityId)) {
+ log.info("SP: " + entityId + " is loaded. Continuing auth. process ... ");
+ } else {
+ log.warn("SP: " + entityId + " is NOT found in configuration. Stopping auth. process ... ");
+ return null;
+
+ }
+
+ } else {
+ log.trace("SP: " + entityId + " is already cached. Use configuration from there ... ");
+ }
+
+ return spConfigCache.get(entityId);
+ }
+
+ @Override
+ public <T> T getServiceProviderConfiguration(String entityId, Class<T> decorator)
+ throws EaafConfigurationException {
+ final ISpConfiguration spConfig = getServiceProviderConfiguration(entityId);
+ if (spConfig != null && decorator != null) {
+ if (decorator.isInstance(spConfig)) {
+ return (T) spConfig;
+ } else {
+ log.error("SPConfig: " + spConfig.getClass().getName() + " is NOT instance of: " + decorator
+ .getName());
+ }
+
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public String validateIdpUrl(URL url) throws EaafException {
+ log.trace("Validate requested URL: " + url);
+ String urlPrefixFromConfig = getBasicConfiguration(
+ MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX);
+ if (StringUtils.isEmpty(urlPrefixFromConfig)) {
+ log.warn("Application config containts NO URL prefix");
+ throw new EaafConfigurationException("config.27",
+ new Object[] { "Application config containts NO "
+ + getApplicationSpecificKeyPrefix()
+ + MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX });
+
+ }
+
+ // remove last slash
+ if (urlPrefixFromConfig.endsWith("/")) {
+ urlPrefixFromConfig = urlPrefixFromConfig.substring(0, urlPrefixFromConfig.length() - 1);
+ }
+
+ if (getBasicConfigurationBoolean(
+ MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_REQUEST_VALIDATION, false)) {
+ if (url != null && url.toExternalForm().startsWith(urlPrefixFromConfig)) {
+ return urlPrefixFromConfig;
+ }
+
+ log.info("URL: " + url + " does NOT match to allowed application prefix: " + urlPrefixFromConfig);
+ return null;
+
+ } else {
+ return urlPrefixFromConfig;
+
+ }
+ }
+
+ @Override
+ public String getApplicationSpecificKeyPrefix() {
+ return MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PREFIX;
+
+ }
+
+ @Override
+ protected String getBackupConfigPath() {
+ return null;
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java
new file mode 100644
index 00000000..5ca1c8c5
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java
@@ -0,0 +1,171 @@
+/*
+ * 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.asitplus.eidas.specific.core.config;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.conf.SpConfigurationImpl;
+import lombok.Getter;
+import lombok.Setter;
+
+public class ServiceProviderConfiguration extends SpConfigurationImpl {
+ private static final long serialVersionUID = 1L;
+ private static final Logger log = LoggerFactory.getLogger(ServiceProviderConfiguration.class);
+
+ private List<String> minimumLoA = Arrays.asList(EaafConstants.EIDAS_LOA_HIGH);
+ private String bpkTargetIdentifier;
+ private String loaMachtingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM;
+
+ @Setter
+ @Getter
+ private List<String> mandateProfiles;
+
+ @Getter
+ @Setter
+ private SpMandateModes mandateMode = SpMandateModes.NONE;
+
+ public ServiceProviderConfiguration(Map<String, String> spConfig, IConfiguration authConfig) {
+ super(spConfig, authConfig);
+
+ }
+
+ @Override
+ public boolean hasBaseIdInternalProcessingRestriction() {
+ return false;
+
+ }
+
+
+ @Override
+ public boolean hasBaseIdTransferRestriction() {
+ final Boolean spConfigPolicy = isConfigurationValue(
+ MsEidasNodeConstants.PROP_CONFIG_SP_POLICY_BASEIDTRANSFER_RESTRICTION);
+ if (spConfigPolicy) {
+ return spConfigPolicy;
+
+ } else {
+ log.trace("SP configuration defines no baseID transfer restriction. Enforce default policy ...");
+ for (final String el : getTargetsWithNoBaseIdTransferRestriction()) {
+ if (this.bpkTargetIdentifier != null && this.bpkTargetIdentifier.startsWith(el)) {
+ log.debug("SP-Target: " + this.bpkTargetIdentifier
+ + " has NO baseID transfer restriction in default policy");
+ return false;
+
+ }
+ }
+ }
+
+ log.debug("Default-policy defines baseID transfer restriction for SP-Target: "
+ + this.bpkTargetIdentifier);
+ return true;
+ }
+
+ @Override
+ public List<String> getRequiredLoA() {
+ return minimumLoA;
+
+ }
+
+ @Override
+ public String getLoAMatchingMode() {
+ return loaMachtingMode;
+
+ }
+
+ @Override
+ public String getAreaSpecificTargetIdentifier() {
+ return bpkTargetIdentifier;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return getConfigurationValue(
+ MsEidasNodeConstants.PROP_CONFIG_SP_FRIENDLYNAME,
+ "NO FRIENDLYNAME SET");
+
+ }
+
+ /**
+ * Set the minimum level of eIDAS authentication for this SP <br>
+ * <b>Default:</b> http://eidas.europa.eu/LoA/high <br>
+ * <b>Info:</b> In case of MINIMUM matching-mode, only one entry is allowed
+ *
+ * @param minimumLoA eIDAS LoA URIs
+ */
+
+ public void setRequiredLoA(List<String> minimumLoA) {
+ this.minimumLoA = minimumLoA;
+ }
+
+ /**
+ * Set the mode of operation for LoA matching for this SP. <b>Default:
+ * minimum</b> <br>
+ * <b>Info:</b> Currently only 'minimum' and 'exact' are supported
+ *
+ * @param mode LoA matching mode according to SAML2 core specification
+ */
+ public void setLoAMachtingMode(String mode) {
+ this.loaMachtingMode = mode;
+ }
+
+ /**
+ * Set the bPK Target for this service provider.
+ *
+ * @param bpkTargetIdentifier Set the bPK sector
+ * @throws EAAFException If the bPKTargetIdentifier is NOT ALLOWED for this
+ * service provider
+ */
+ public void setBpkTargetIdentifier(String bpkTargetIdentifier) throws EaafException {
+ final String allowedTargetIdentifierRegExPattern = getConfigurationValue(
+ MsEidasNodeConstants.PROP_CONFIG_SP_POLICY_ALLOWED_TARGETS,
+ MsEidasNodeConstants.POLICY_DEFAULT_ALLOWED_TARGETS);
+ log.trace("Use bPK-target regex pattern: " + allowedTargetIdentifierRegExPattern);
+
+ final Pattern p = Pattern.compile(allowedTargetIdentifierRegExPattern);
+ final Matcher m = p.matcher(bpkTargetIdentifier);
+ if (m.matches()) {
+ log.debug("Requested bPK-target: " + bpkTargetIdentifier + " matches regex pattern");
+ this.bpkTargetIdentifier = bpkTargetIdentifier;
+
+ } else {
+ log.warn("Requested bPK-target: " + bpkTargetIdentifier + " does NOT match regex pattern.");
+ throw new EaafException("auth.37", new Object[] { bpkTargetIdentifier, getUniqueIdentifier() });
+
+ }
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/SpringBootBasicConfigurationProvider.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/SpringBootBasicConfigurationProvider.java
new file mode 100644
index 00000000..f5492913
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/SpringBootBasicConfigurationProvider.java
@@ -0,0 +1,122 @@
+package at.asitplus.eidas.specific.core.config;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.conf.AbstractSpringBootConfigurationImpl;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SpringBootBasicConfigurationProvider extends AbstractSpringBootConfigurationImpl {
+
+ private final Map<String, ISpConfiguration> spConfigCache = new HashMap<>();
+
+ @Override
+ public ISpConfiguration getServiceProviderConfiguration(String entityId) throws EaafConfigurationException {
+ if (!spConfigCache.containsKey(entityId)) {
+ log.debug("SP: " + entityId + " is NOT cached. Starting load operation ... ");
+ final Map<String, String> allSPs = getBasicConfigurationWithPrefix(
+ MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX);
+ for (Entry<String, String> entry : allSPs.entrySet()) {
+ if (entry.getKey().endsWith(MsEidasNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER)
+ && entry.getValue().equals(entityId)) {
+ final String listId = KeyValueUtils.getParentKey(entry.getKey());
+ log.trace("Find SP configuration with list-Id: " + listId
+ + ". Extracting configuration elements ... ");
+ final Map<String, String> spConfig = KeyValueUtils.getSubSetWithPrefix(allSPs, listId
+ + KeyValueUtils.KEY_DELIMITER);
+ spConfigCache.put(entityId,
+ new ServiceProviderConfiguration(spConfig, this));
+ break;
+ }
+ }
+
+ if (spConfigCache.containsKey(entityId)) {
+ log.info("SP: " + entityId + " is loaded. Continuing auth. process ... ");
+ } else {
+ log.warn("SP: " + entityId + " is NOT found in configuration. Stopping auth. process ... ");
+ return null;
+
+ }
+
+ } else {
+ log.trace("SP: " + entityId + " is already cached. Use configuration from there ... ");
+ }
+
+ return spConfigCache.get(entityId);
+ }
+
+ @Override
+ public <T> T getServiceProviderConfiguration(String entityId, Class<T> decorator)
+ throws EaafConfigurationException {
+ final ISpConfiguration spConfig = getServiceProviderConfiguration(entityId);
+ if (spConfig != null && decorator != null) {
+ if (decorator.isInstance(spConfig)) {
+ return (T) spConfig;
+ } else {
+ log.error("SPConfig: " + spConfig.getClass().getName() + " is NOT instance of: " + decorator
+ .getName());
+ }
+
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public String validateIdpUrl(URL url) throws EaafException {
+ log.trace("Validate requested URL: " + url);
+ String urlPrefixFromConfig = getBasicConfiguration(
+ MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX);
+ if (StringUtils.isEmpty(urlPrefixFromConfig)) {
+ log.warn("Application config containts NO URL prefix");
+ throw new EaafConfigurationException("config.27",
+ new Object[] { "Application config containts NO "
+ + getApplicationSpecificKeyPrefix()
+ + MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_PREFIX });
+
+ }
+
+ // remove last slash
+ if (urlPrefixFromConfig.endsWith("/")) {
+ urlPrefixFromConfig = urlPrefixFromConfig.substring(0, urlPrefixFromConfig.length() - 1);
+ }
+
+ if (getBasicConfigurationBoolean(
+ MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PUBLIC_URL_REQUEST_VALIDATION, false)) {
+ if (url != null && url.toExternalForm().startsWith(urlPrefixFromConfig)) {
+ return urlPrefixFromConfig;
+ }
+
+ log.info("URL: " + url + " does NOT match to allowed application prefix: " + urlPrefixFromConfig);
+ return null;
+
+ } else {
+ return urlPrefixFromConfig;
+
+ }
+ }
+
+ @Override
+ public String getApplicationSpecificKeyPrefix() {
+ return MsEidasNodeConstants.PROP_CONFIG_APPLICATION_PREFIX;
+
+ }
+
+ @Override
+ protected String getBackupConfigPath() {
+ return null;
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java
new file mode 100644
index 00000000..96d58def
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/DefaultVelocityGuiBuilderImpl.java
@@ -0,0 +1,77 @@
+/*
+ * 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.asitplus.eidas.specific.core.gui;
+
+import java.io.InputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
+import at.gv.egiz.eaaf.core.impl.gui.AbstractVelocityGuiFormBuilderImpl;
+
+@Service("velocityGUIBuilderImpl")
+public class DefaultVelocityGuiBuilderImpl extends AbstractVelocityGuiFormBuilderImpl {
+ private static final Logger log = LoggerFactory.getLogger(DefaultVelocityGuiBuilderImpl.class);
+
+ private static final String CLASSPATH_HTMLTEMPLATES_DIR = "templates/";
+
+ public DefaultVelocityGuiBuilderImpl() throws GuiBuildException {
+ super();
+
+ }
+
+ @Override
+ protected InputStream getInternalTemplate(IVelocityGuiBuilderConfiguration config)
+ throws GuiBuildException {
+ final String viewName = config.getViewName();
+ log.debug("GUI template:" + viewName + " is not found in configuration directory. "
+ + " Load template from project library ... ");
+ final String pathLocation = getInternalClasspathTemplateDir(config, CLASSPATH_HTMLTEMPLATES_DIR)
+ + viewName;
+ try {
+ final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(pathLocation);
+ return is;
+
+ } catch (final Exception e1) {
+ log.error("GUI template:" + pathLocation + " is NOT loadable from classpath!", e1);
+ throw new GuiBuildException("GUI template:" + pathLocation + " is NOT loadable from classpath!", e1);
+
+ }
+ }
+
+ @Override
+ public String evaluateResponseContentType(HttpServletRequest httpReq, IGuiBuilderConfiguration config,
+ String loggerName) throws GuiBuildException {
+ return MediaType.TEXT_HTML_VALUE;
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java
new file mode 100644
index 00000000..62a0005d
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/GuiBuilderConfigurationFactory.java
@@ -0,0 +1,69 @@
+/*
+ * 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.asitplus.eidas.specific.core.gui;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+
+import javax.annotation.Nonnull;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Service;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration;
+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.idp.IConfiguration;
+
+@Service("GUIBuilderConfigurationFactory")
+public class GuiBuilderConfigurationFactory implements IGuiBuilderConfigurationFactory {
+ @Autowired(required = true) private IConfiguration basicConfig;
+ @Autowired(required = true) private ResourceLoader resourceLoader;
+
+ @Override
+ public IGuiBuilderConfiguration getDefaultErrorGui(String authUrl) {
+ return new StaticGuiBuilderConfiguration(basicConfig, authUrl, MsEidasNodeConstants.TEMPLATE_HTML_ERROR,
+ null, resourceLoader);
+ }
+
+ @Override
+ public IVelocityGuiBuilderConfiguration getSpSpecificSaml2PostConfiguration(IRequest pendingReq,
+ String viewName, URI configRootContextDir)
+ throws MalformedURLException {
+ return new StaticGuiBuilderConfiguration(basicConfig, pendingReq,
+ MsEidasNodeConstants.TEMPLATE_HTML_PVP_POSTBINDING, null, resourceLoader);
+ }
+
+ @Override
+ public IGuiBuilderConfiguration getDefaultIFrameParentHopGui(IRequest pendingReq,
+ @Nonnull String endpoint, @Nonnull String errorId) {
+ //TODO: implement if iFrame to parent hop is needed
+ throw new RuntimeException("Operation not supported yet.");
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java
new file mode 100644
index 00000000..0fd85d3d
--- /dev/null
+++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/gui/StaticGuiBuilderConfiguration.java
@@ -0,0 +1,148 @@
+/*
+ * 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.asitplus.eidas.specific.core.gui;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.text.StringEscapeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.gui.GroupDefinition;
+import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+
+public class StaticGuiBuilderConfiguration extends AbstractGuiFormBuilderConfiguration implements
+ IVelocityGuiBuilderConfiguration, ModifyableGuiBuilderConfiguration {
+ private static final Logger log = LoggerFactory.getLogger(StaticGuiBuilderConfiguration.class);
+
+ private IRequest pendingReq = null;
+ private IConfiguration basicConfig = null;
+ private ResourceLoader resourceLoader;
+
+ /**
+ * Static resource configuration for GUI Builder implementations.
+ *
+ * @param basicConfig basicConfig
+ * @param authUrl Public URL of the application
+ * @param viewName Name of the template
+ * @param formSubmitEndpoint Form Submit end-point, if template contains a form.
+ * @param resourceLoader Spring ResourceLoader implementation
+ */
+ public StaticGuiBuilderConfiguration(IConfiguration basicConfig, String authUrl, String viewName,
+ String formSubmitEndpoint, ResourceLoader resourceLoader) {
+ super(authUrl, viewName, formSubmitEndpoint);
+ this.basicConfig = basicConfig;
+ this.resourceLoader = resourceLoader;
+
+ }
+
+ /**
+ * Static resource configuration for GUI Builder implementations.
+ *
+ * @param basicConfig Application configuration
+ * @param pendingReq Current pending request
+ * @param viewName Name of the template
+ * @param formSubmitEndpoint Form Submit end-point, if template contains a form.
+ * @param resourceLoader Spring ResourceLoader implementation
+ */
+ public StaticGuiBuilderConfiguration(IConfiguration basicConfig, IRequest pendingReq, String viewName,
+ String formSubmitEndpoint, ResourceLoader resourceLoader) {
+ super(pendingReq.getAuthUrl(), viewName, formSubmitEndpoint);
+ this.pendingReq = pendingReq;
+ this.basicConfig = basicConfig;
+ this.resourceLoader = resourceLoader;
+
+ }
+
+ @Override
+ public String getClasspathTemplateDir() {
+ return MsEidasNodeConstants.CLASSPATH_TEMPLATE_DIR;
+
+ }
+
+ @Override
+ public String getDefaultContentType() {
+ return null;
+
+ }
+
+ @Override
+ public InputStream getTemplate(String viewName) {
+ final String templateUrl = MsEidasNodeConstants.FILESYSTEM_TEMPLATE_DIR + viewName;
+ try {
+ final String absUrl = FileUtils.makeAbsoluteUrl(templateUrl, this.basicConfig
+ .getConfigurationRootDirectory());
+ log.debug("Load template URL for view: " + viewName + " from: " + absUrl);
+ Resource resource = resourceLoader.getResource(absUrl);
+ return resource.getInputStream();
+
+ } catch (IOException e) {
+ log.info("Can can build filesytem path to template: " + templateUrl
+ + " Reason: " + e.getMessage());
+
+ }
+
+ return null;
+ }
+
+ @Override
+ public void putCustomParameterWithOutEscaption(GroupDefinition group, String key, Object value) {
+ setViewParameter(getFromGroup(), key, value);
+
+ }
+
+ @Override
+ public void putCustomParameter(GroupDefinition group, String key, String value) {
+ setViewParameter(getFromGroup(), key, StringEscapeUtils.escapeHtml4(value));
+
+ }
+
+ @Override
+ protected void putSpecificViewParameters() {
+ if (pendingReq != null) {
+ setViewParameter(getFromGroup(), PARAM_PENDINGREQUESTID, StringEscapeUtils.escapeHtml4(pendingReq
+ .getPendingRequestId()));
+ setViewParameter(getFromGroup(), PARAM_PENDINGREQUESTID_DEPRECATED, StringEscapeUtils.escapeHtml4(
+ pendingReq.getPendingRequestId()));
+
+ }
+
+ }
+
+ @Override
+ protected GroupDefinition getFromGroup() {
+ return null;
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/main/resources/common_gui.beans.xml b/modules/core_common_lib/src/main/resources/common_gui.beans.xml
new file mode 100644
index 00000000..969a40f7
--- /dev/null
+++ b/modules/core_common_lib/src/main/resources/common_gui.beans.xml
@@ -0,0 +1,60 @@
+<?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"
+ xmlns:task="http://www.springframework.org/schema/task"
+ 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
+ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
+
+ <bean id="contentNegotiationManager"
+ class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"
+ primary="true">
+ <property name="parameterName" value="mediaType" />
+ <property name="defaultContentType" value="application/json" />
+ <property name="useRegisteredExtensionsOnly" value="false" />
+ <property name="mediaTypes">
+ <map>
+ <entry key="json" value="application/json" />
+ <entry key="html" value="text/html" />
+ </map>
+ </property>
+ </bean>
+
+ <bean
+ class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
+ <property name="order" value="1" />
+ <property name="defaultViews">
+ <list>
+ <!-- JSON View -->
+ <bean
+ class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
+ <property name="contentType" value="application/json" />
+ </bean>
+ </list>
+ </property>
+ </bean>
+
+
+ <bean id="templateEngine"
+ class="org.thymeleaf.spring5.SpringTemplateEngine">
+ <property name="templateResolver" ref="templateResolver" />
+ </bean>
+
+ <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
+ <property name="order" value="2" />
+ <property name="templateEngine" ref="templateEngine" />
+ <property name="characterEncoding" value="UTF-8" />
+ </bean>
+
+ <bean id="valitatorWithI18nSupport"
+ class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
+ <property name="validationMessageSource"
+ ref="messageSource" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/BasicConfigProviderTest.java b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/BasicConfigProviderTest.java
new file mode 100644
index 00000000..224618b9
--- /dev/null
+++ b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/BasicConfigProviderTest.java
@@ -0,0 +1,156 @@
+package at.asitplus.eidas.specific.core.test.config;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_basic_realConfig.xml"})
+@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
+public class BasicConfigProviderTest {
+
+ @Autowired private IConfigurationWithSP basicConfig;
+
+ /**
+ * jUnit class initializer.
+ *
+ */
+ @BeforeClass
+ public static void classInitializer() {
+ final String current = new java.io.File(".").toURI().toString();
+ System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_1.properties");
+
+ }
+
+ @Test
+ public void configPropInfos() {
+ Assert.assertEquals("size", 2, MsEidasNodeConstants.COUNTRY_SELECTION_PARAM_WHITELIST.size());
+
+ }
+
+ @Test
+ public void loadSpNoExist() throws EaafConfigurationException {
+ ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(
+ RandomStringUtils.randomAlphabetic(5));
+ Assert.assertNull("spConfig", spConfig);
+
+ }
+
+ @Test
+ public void loadSpConfigBasicMode() throws EaafConfigurationException {
+ ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration("jUnitTest1");
+
+ Assert.assertNotNull("spConfig", spConfig);
+ Assert.assertEquals("uniqueId", "jUnitTest1", spConfig.getUniqueIdentifier());
+ Assert.assertEquals("friendlyName", "NO FRIENDLYNAME SET", spConfig.getFriendlyName());
+ Assert.assertEquals("pvp2.truststore", "", spConfig.getConfigurationValue("pvp2.metadata.truststore"));
+ String test = RandomStringUtils.randomAlphabetic(5);
+ Assert.assertEquals("pvp2.password", "1234pass",
+ spConfig.getConfigurationValue("pvp2.metadata.truststore.password", test));
+ Assert.assertEquals("eidMode", true, spConfig.isConfigurationValue("newEidMode"));
+ Assert.assertEquals("notexistflag", false, spConfig.isConfigurationValue("notexist", false));
+ Assert.assertNotNull("fullConfig", spConfig.getFullConfiguration());
+ Assert.assertEquals("fullConfig", 4, spConfig.getFullConfiguration().size());
+
+ }
+
+ @Test
+ public void loadSpConfigAdvancedMode() throws EaafConfigurationException {
+ ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(
+ "jUnitTest2", ServiceProviderConfiguration.class);
+
+ Assert.assertNotNull("spConfig", spConfig);
+ Assert.assertEquals("uniqueId", "jUnitTest2", spConfig.getUniqueIdentifier());
+ Assert.assertEquals("friendlyName", "jUnit tester 2", spConfig.getFriendlyName());
+ Assert.assertEquals("pvp2.truststore", "", spConfig.getConfigurationValue("pvp2.metadata.truststore"));
+ String test = RandomStringUtils.randomAlphabetic(5);
+ Assert.assertEquals("pvp2.password", test,
+ spConfig.getConfigurationValue("pvp2.metadata.truststore.notexist", test));
+ Assert.assertEquals("eidMode", false, spConfig.isConfigurationValue("newEidMode"));
+ Assert.assertEquals("notexistflag", false, spConfig.isConfigurationValue("notexist", false));
+ Assert.assertNotNull("fullConfig", spConfig.getFullConfiguration());
+ Assert.assertEquals("fullConfig", 5, spConfig.getFullConfiguration().size());
+ Assert.assertFalse("baseIdInternal", spConfig.hasBaseIdInternalProcessingRestriction());
+ Assert.assertTrue("baseIdTransfer", spConfig.hasBaseIdTransferRestriction());
+
+ }
+
+ @Test
+ public void loadSpConfigAdvancedModeWrongDecorator() throws EaafConfigurationException {
+ ISpConfiguration spConfig1 = basicConfig.getServiceProviderConfiguration(
+ "jUnitTest2", null);
+ Assert.assertNull("spConfig", spConfig1);
+
+ String spConfig2 = basicConfig.getServiceProviderConfiguration(
+ "jUnitTest2", String.class);
+ Assert.assertNull("spConfig", spConfig2);
+
+ }
+
+ @Test
+ public void loadConfigValuesString() {
+ Assert.assertEquals("without default", "ownSpecificConnector",
+ basicConfig.getBasicConfiguration("auth.eIDAS.node_v2.entityId"));
+
+ Assert.assertEquals("with default", "",
+ basicConfig.getBasicConfiguration("auth.eIDAS.szrclient.endpoint.prod",
+ RandomStringUtils.randomAlphabetic(5)));
+
+ String rand1 = RandomStringUtils.randomAlphanumeric(5);
+ Assert.assertEquals("unknown with default", rand1,
+ basicConfig.getBasicConfiguration("notexist", rand1));
+
+ }
+
+ @Test
+ public void loadConfigValuesBoolean() {
+ Assert.assertEquals("without default", true,
+ basicConfig.getBasicConfigurationBoolean("auth.eIDAS.szrclient.useTestService"));
+
+ Assert.assertEquals("with default", false,
+ basicConfig.getBasicConfigurationBoolean("auth.notexist",
+ false));
+
+ Assert.assertEquals("unknown with default", false,
+ basicConfig.getBasicConfigurationBoolean("auth.eIDAS.szrclient.params.vkz", true));
+
+ }
+
+ @Test
+ public void loadConfigMap() {
+ Map<String, String> entries = basicConfig.getBasicConfigurationWithPrefix("auth.eIDAS.szrclient");
+ Assert.assertEquals("wrong size", 16, entries.size());
+ Assert.assertTrue("missing element", entries.containsKey("endpoint.test"));
+ Assert.assertEquals("wrong entry", "http://localhost:1234/demoszr", entries.get("endpoint.test"));
+
+ }
+
+ @Test
+ public void validateUrl() throws MalformedURLException, EaafException {
+ Assert.assertEquals("wrong URL", "http://localhost/test",
+ basicConfig.validateIdpUrl(new URL("http://localhost/test/" + RandomStringUtils.randomAlphabetic(5))));
+
+ Assert.assertNull("wrong URL",
+ basicConfig.validateIdpUrl(new URL("http://localhost/wrong/" + RandomStringUtils.randomAlphabetic(5))));
+
+ }
+}
diff --git a/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/ServiceProviderConfigurationTest.java b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/ServiceProviderConfigurationTest.java
new file mode 100644
index 00000000..99ea2a47
--- /dev/null
+++ b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/ServiceProviderConfigurationTest.java
@@ -0,0 +1,54 @@
+package at.asitplus.eidas.specific.core.test.config;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class ServiceProviderConfigurationTest {
+
+
+
+ @Test
+ public void spConfigLoad() throws EaafException {
+ IConfiguration authConfig = new MsConnectorDummyConfigMap();
+
+ Map<String, String> map = new HashMap<>();
+ map.put("uniqueID", RandomStringUtils.randomAlphabetic(10));
+ map.put("policy.allowed.requested.targets", "urn:publicid:gv.at:cdid\\+.*");
+
+ ServiceProviderConfiguration spConfig = new ServiceProviderConfiguration(map, authConfig);
+
+ spConfig.setRequiredLoA(Arrays.asList(EaafConstants.EIDAS_LOA_LOW));
+ Assert.assertEquals("LoA", 1, spConfig.getRequiredLoA().size());
+ Assert.assertEquals("LoA", "http://eidas.europa.eu/LoA/low", spConfig.getRequiredLoA().get(0));
+
+ spConfig.setLoAMachtingMode("exact");
+ Assert.assertEquals("wrong machtingMode", "exact", spConfig.getLoAMatchingMode());
+
+ String bpkTarget = EaafConstants.URN_PREFIX_CDID + RandomStringUtils.randomAlphabetic(2);
+ spConfig.setBpkTargetIdentifier(bpkTarget);
+ Assert.assertEquals("wrong bPK", bpkTarget, spConfig.getAreaSpecificTargetIdentifier());
+
+
+ try {
+ spConfig.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_WBPK + RandomStringUtils.randomAlphabetic(2));
+
+ } catch (EaafException e) {
+ Assert.assertEquals("ErrorId", "auth.37", e.getErrorId());
+ }
+
+ }
+}
diff --git a/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/SpringBootBasicConfigurationProviderTest.java b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/SpringBootBasicConfigurationProviderTest.java
new file mode 100644
index 00000000..0dd34494
--- /dev/null
+++ b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/SpringBootBasicConfigurationProviderTest.java
@@ -0,0 +1,148 @@
+package at.asitplus.eidas.specific.core.test.config;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/SpringTest-context_basic_realConfig.xml"})
+@TestPropertySource(locations = { "/config/junit_config_1.properties" })
+@ActiveProfiles("springBoot")
+@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
+public class SpringBootBasicConfigurationProviderTest {
+
+ @Autowired private IConfigurationWithSP basicConfig;
+
+ @Test
+ public void configPropInfos() {
+ Assert.assertEquals("size", 2, MsEidasNodeConstants.COUNTRY_SELECTION_PARAM_WHITELIST.size());
+
+ }
+
+ @Test
+ public void loadSpNoExist() throws EaafConfigurationException {
+ ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(
+ RandomStringUtils.randomAlphabetic(5));
+ Assert.assertNull("spConfig", spConfig);
+
+ }
+
+ @Test
+ public void loadSpConfigBasicMode() throws EaafConfigurationException {
+ ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration("jUnitTest1");
+
+ Assert.assertNotNull("spConfig", spConfig);
+ Assert.assertEquals("uniqueId", "jUnitTest1", spConfig.getUniqueIdentifier());
+ Assert.assertEquals("friendlyName", "NO FRIENDLYNAME SET", spConfig.getFriendlyName());
+ Assert.assertEquals("pvp2.truststore", "", spConfig.getConfigurationValue("pvp2.metadata.truststore"));
+ String test = RandomStringUtils.randomAlphabetic(5);
+ Assert.assertEquals("pvp2.password", "1234pass",
+ spConfig.getConfigurationValue("pvp2.metadata.truststore.password", test));
+ Assert.assertEquals("eidMode", true, spConfig.isConfigurationValue("newEidMode"));
+ Assert.assertEquals("notexistflag", false, spConfig.isConfigurationValue("notexist", false));
+ Assert.assertNotNull("fullConfig", spConfig.getFullConfiguration());
+ Assert.assertEquals("fullConfig", 4, spConfig.getFullConfiguration().size());
+
+ }
+
+ @Test
+ public void loadSpConfigAdvancedMode() throws EaafConfigurationException {
+ ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(
+ "jUnitTest2", ServiceProviderConfiguration.class);
+
+ Assert.assertNotNull("spConfig", spConfig);
+ Assert.assertEquals("uniqueId", "jUnitTest2", spConfig.getUniqueIdentifier());
+ Assert.assertEquals("friendlyName", "jUnit tester 2", spConfig.getFriendlyName());
+ Assert.assertEquals("pvp2.truststore", "", spConfig.getConfigurationValue("pvp2.metadata.truststore"));
+ String test = RandomStringUtils.randomAlphabetic(5);
+ Assert.assertEquals("pvp2.password", test,
+ spConfig.getConfigurationValue("pvp2.metadata.truststore.notexist", test));
+ Assert.assertEquals("eidMode", false, spConfig.isConfigurationValue("newEidMode"));
+ Assert.assertEquals("notexistflag", false, spConfig.isConfigurationValue("notexist", false));
+ Assert.assertNotNull("fullConfig", spConfig.getFullConfiguration());
+ Assert.assertEquals("fullConfig", 5, spConfig.getFullConfiguration().size());
+ Assert.assertFalse("baseIdInternal", spConfig.hasBaseIdInternalProcessingRestriction());
+ Assert.assertTrue("baseIdTransfer", spConfig.hasBaseIdTransferRestriction());
+
+ }
+
+ @Test
+ public void loadSpConfigAdvancedModeWrongDecorator() throws EaafConfigurationException {
+ ISpConfiguration spConfig1 = basicConfig.getServiceProviderConfiguration(
+ "jUnitTest2", null);
+ Assert.assertNull("spConfig", spConfig1);
+
+ String spConfig2 = basicConfig.getServiceProviderConfiguration(
+ "jUnitTest2", String.class);
+ Assert.assertNull("spConfig", spConfig2);
+
+ }
+
+ @Test
+ public void loadConfigValuesString() {
+ Assert.assertEquals("without default", "ownSpecificConnector",
+ basicConfig.getBasicConfiguration("auth.eIDAS.node_v2.entityId"));
+
+ Assert.assertEquals("with default", "",
+ basicConfig.getBasicConfiguration("auth.eIDAS.szrclient.endpoint.prod",
+ RandomStringUtils.randomAlphabetic(5)));
+
+ String rand1 = RandomStringUtils.randomAlphanumeric(5);
+ Assert.assertEquals("unknown with default", rand1,
+ basicConfig.getBasicConfiguration("notexist", rand1));
+
+ }
+
+ @Test
+ public void loadConfigValuesBoolean() {
+ Assert.assertEquals("without default", true,
+ basicConfig.getBasicConfigurationBoolean("auth.eIDAS.szrclient.useTestService"));
+
+ Assert.assertEquals("not exist with default", false,
+ basicConfig.getBasicConfigurationBoolean("auth.notexist",
+ false));
+
+ Assert.assertEquals("exist but empty with default", true,
+ basicConfig.getBasicConfigurationBoolean("auth.eIDAS.szrclient.params.vkz", true));
+
+ }
+
+ @Test
+ public void loadConfigMap() {
+ Map<String, String> entries = basicConfig.getBasicConfigurationWithPrefix("auth.eIDAS.szrclient");
+ Assert.assertEquals("wrong size", 16, entries.size());
+ Assert.assertTrue("missing element", entries.containsKey("endpoint.test"));
+ Assert.assertEquals("wrong entry", "http://localhost:1234/demoszr", entries.get("endpoint.test"));
+
+ }
+
+ @Test
+ public void validateUrl() throws MalformedURLException, EaafException {
+ Assert.assertEquals("wrong URL", "http://localhost/test",
+ basicConfig.validateIdpUrl(new URL("http://localhost/test/" + RandomStringUtils.randomAlphabetic(5))));
+
+ Assert.assertNull("wrong URL",
+ basicConfig.validateIdpUrl(new URL("http://localhost/wrong/" + RandomStringUtils.randomAlphabetic(5))));
+
+ }
+}
diff --git a/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummyConfigMap.java b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummyConfigMap.java
new file mode 100644
index 00000000..59ae5aff
--- /dev/null
+++ b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummyConfigMap.java
@@ -0,0 +1,120 @@
+package at.asitplus.eidas.specific.core.test.config.dummy;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap;
+import lombok.Setter;
+
+/**
+ * MS-Connector specific dummy basic-config implementation.
+ *
+ * @author tlenz
+ *
+ */
+public class MsConnectorDummyConfigMap extends DummyAuthConfigMap {
+
+ private static final String CONFIG_PREFIX = "eidas.ms.";
+
+ @Setter
+ private String configRootDirSufix;
+
+ /**
+ * Creates an emptry configuration.
+ *
+ */
+ public MsConnectorDummyConfigMap() {
+
+ }
+
+ /**
+ * Dummy Application-configuration.
+ *
+ * @param configIs Property based configuration
+ * @throws IOException In case of an configuration read error
+ */
+ public MsConnectorDummyConfigMap(final InputStream configIs) throws IOException {
+ super(configIs);
+
+ }
+
+ /**
+ * Dummy Application-configuration.
+ *
+ * @param path Path to property based configuration
+ * @throws IOException In case of an configuration read error
+ */
+ public MsConnectorDummyConfigMap(final String path) throws IOException {
+ super(path);
+
+ }
+
+
+ @Override
+ public String getBasicConfiguration(final String key) {
+ return super.getBasicConfiguration(addPrefixToKey(key));
+
+ }
+
+ @Override
+ public String validateIdpUrl(final URL authReqUrl) throws EaafException {
+ return authReqUrl.toExternalForm();
+
+ }
+
+ @Override
+ public Map<String, String> getBasicConfigurationWithPrefix(final String prefix) {
+ return super.getBasicConfigurationWithPrefix(addPrefixToKey(prefix));
+
+ }
+
+ @Override
+ public void putConfigValue(final String key, final String value) {
+ super.putConfigValue(addPrefixToKey(key), value);
+ }
+
+ @Override
+ public void removeConfigValue(final String key) {
+ super.removeConfigValue(addPrefixToKey(key));
+
+ }
+
+ @Override
+ public URI getConfigurationRootDirectory() {
+ URI basePath = super.getConfigurationRootDirectory();
+ if (StringUtils.isNotEmpty(configRootDirSufix)) {
+ try {
+ return new URI(basePath.toString() + configRootDirSufix);
+
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Wrong Dummyconfig", e);
+
+ }
+
+ } else {
+ return basePath;
+
+ }
+
+
+ }
+
+ private String addPrefixToKey(final String key) {
+ if (key.startsWith(CONFIG_PREFIX)) {
+ return key;
+
+ } else {
+ return CONFIG_PREFIX + key;
+
+ }
+ }
+
+
+}
diff --git a/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummySpConfiguration.java b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummySpConfiguration.java
new file mode 100644
index 00000000..922a13b7
--- /dev/null
+++ b/modules/core_common_lib/src/test/java/at/asitplus/eidas/specific/core/test/config/dummy/MsConnectorDummySpConfiguration.java
@@ -0,0 +1,28 @@
+package at.asitplus.eidas.specific.core.test.config.dummy;
+
+import java.util.List;
+import java.util.Map;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import lombok.Setter;
+
+public class MsConnectorDummySpConfiguration extends DummySpConfiguration {
+
+ private static final long serialVersionUID = -3249018889871026127L;
+
+ @Setter
+ private List<String> loa;
+
+ public MsConnectorDummySpConfiguration(Map<String, String> spConfig, IConfiguration authConfig) {
+ super(spConfig, authConfig);
+
+ }
+
+ @Override
+ public List<String> getRequiredLoA() {
+ return loa;
+
+ }
+
+}
diff --git a/modules/core_common_lib/src/test/resources/SpringTest-context_basic_realConfig.xml b/modules/core_common_lib/src/test/resources/SpringTest-context_basic_realConfig.xml
new file mode 100644
index 00000000..66abbb39
--- /dev/null
+++ b/modules/core_common_lib/src/test/resources/SpringTest-context_basic_realConfig.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">
+
+ <context:annotation-config />
+
+ <beans profile="!springBoot">
+ <bean id="BasicMSSpecificNodeConfig"
+ class="at.asitplus.eidas.specific.core.config.BasicConfigurationProvider">
+ <constructor-arg value="#{systemProperties['eidas.ms.configuration']}" />
+ </bean>
+ </beans>
+ <beans profile="springBoot">
+ <bean id="springBootMsSpecificNodeConfig"
+ class="at.asitplus.eidas.specific.core.config.SpringBootBasicConfigurationProvider" />
+ </beans>
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_lib/src/test/resources/config/junit_config_1.properties b/modules/core_common_lib/src/test/resources/config/junit_config_1.properties
new file mode 100644
index 00000000..160725d4
--- /dev/null
+++ b/modules/core_common_lib/src/test/resources/config/junit_config_1.properties
@@ -0,0 +1,124 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=http://localhost/test/
+eidas.ms.context.url.request.validation=true
+eidas.ms.core.configRootDir=file:./src/test/resources/config/
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=
+eidas.ms.auth.eIDAS.node_v2.forward.method=POST
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true
+eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs=myNode
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.8=testtest,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.path=keys/.....
+eidas.ms.pvp2.keystore.password=
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=jUnitTest1
+eidas.ms.sp.0.pvp2.metadata.truststore=
+eidas.ms.sp.0.pvp2.metadata.truststore.password=1234pass
+eidas.ms.sp.0.newEidMode=true
+
+eidas.ms.sp.1.uniqueID=jUnitTest2
+eidas.ms.sp.1.friendlyName=jUnit tester 2
+eidas.ms.sp.1.pvp2.metadata.truststore=
+eidas.ms.sp.1.pvp2.metadata.truststore.password=
+eidas.ms.sp.1.newEidMode=false
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/core_common_webapp/checks/spotbugs-exclude.xml b/modules/core_common_webapp/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..fbab3b53
--- /dev/null
+++ b/modules/core_common_webapp/checks/spotbugs-exclude.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+ <Match>
+ <!-- Builder pattern does not expose date elements -->
+ <OR>
+ <Class name="at.asitplus.eidas.specific.core.health.IgniteClusterHealthIndicator" />
+ </OR>
+ <OR>
+ <Bug pattern="EI_EXPOSE_REP2" />
+ </OR>
+ </Match>
+</FindBugsFilter>
diff --git a/modules/core_common_webapp/pom.xml b/modules/core_common_webapp/pom.xml
new file mode 100644
index 00000000..b36153e6
--- /dev/null
+++ b/modules/core_common_webapp/pom.xml
@@ -0,0 +1,136 @@
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>core_common_webapp</artifactId>
+ <name>WebApplication commons</name>
+
+ <repositories>
+ <repository>
+ <id>eIDASNode-local</id>
+ <name>local</name>
+ <url>file:${basedir}/../../repository</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ </dependency>
+
+ <!-- Third party libs -->
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-jcache-ignite-specific-communication</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.thymeleaf</groupId>
+ <artifactId>thymeleaf-spring5</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>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-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_sp</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_idp</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_idp</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <finalName>core_common_webapp</finalName>
+
+ <plugins>
+ <!-- enable co-existence of testng and junit -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs-maven-plugin</artifactId>
+ <version>${spotbugs-maven-plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java
new file mode 100644
index 00000000..81f23841
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java
@@ -0,0 +1,170 @@
+package at.asitplus.eidas.specific.core;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+
+import at.gv.egiz.components.spring.api.IDestroyableObject;
+import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication;
+
+/**
+ * SpringContext CloseHandler.
+ *
+ * @author tlenz
+ *
+ */
+
+public class SpringContextCloseHandler
+ implements ApplicationListener<ContextClosedEvent>, ApplicationContextAware, BeanPostProcessor {
+
+ private static final Logger log =
+ org.slf4j.LoggerFactory.getLogger(SpringContextCloseHandler.class);
+
+ private ApplicationContext context;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.
+ * springframework.context. ApplicationEvent)
+ */
+ @Override
+ @EventListener
+ public void onApplicationEvent(final ContextClosedEvent arg0) {
+ log.info("MS-specific eIDAS-Node shutdown process started ...");
+
+ try {
+ log.debug("CleanUp objects with implements the IDestroyable interface ... ");
+ final Map<String, IDestroyableObject> objectsToDestroy =
+ context.getBeansOfType(IDestroyableObject.class);
+ internalIDestroyableObject(objectsToDestroy);
+ log.info("Object cleanUp complete");
+
+ log.debug("Stopping Spring Thread-Pools ... ");
+ // shut-down task schedulers
+ final Map<String, ThreadPoolTaskScheduler> schedulers =
+ context.getBeansOfType(ThreadPoolTaskScheduler.class);
+ internalThreadPoolTaskScheduler(schedulers);
+
+ // shut-down task executors
+ final Map<String, ThreadPoolTaskExecutor> executers =
+ context.getBeansOfType(ThreadPoolTaskExecutor.class);
+ internalThreadPoolTaskExecutor(executers);
+ log.debug("Spring Thread-Pools stopped");
+
+
+ //clean-up eIDAS node
+ Map<String, IgniteInstanceInitializerSpecificCommunication> nodeIgnite =
+ context.getBeansOfType(IgniteInstanceInitializerSpecificCommunication.class);
+ log.info("Find #{} Apache Ignite instances from eIDAS Ref. impl.", nodeIgnite.size());
+ for (Entry<String, IgniteInstanceInitializerSpecificCommunication> el : nodeIgnite.entrySet()) {
+ if (el.getValue().getInstance() != null) {
+ el.getValue().getInstance().close();
+ el.getValue().destroyInstance();
+ log.debug("Shutdown Apache-Ignite: {}", el.getKey());
+
+ }
+ }
+
+ log.info("MS-specific eIDAS-Node shutdown process finished");
+
+ } catch (final Exception e) {
+ log.warn("MS-specific eIDAS-Node shutdown process has an error.", e);
+
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.beans.factory.config.BeanPostProcessor#
+ * postProcessAfterInitialization(java. lang.Object, java.lang.String)
+ */
+ @Override
+ public Object postProcessAfterInitialization(final Object arg0, final String arg1)
+ throws BeansException {
+ if (arg0 instanceof ThreadPoolTaskScheduler) {
+ ((ThreadPoolTaskScheduler) arg0).setWaitForTasksToCompleteOnShutdown(true);
+ }
+ if (arg0 instanceof ThreadPoolTaskExecutor) {
+ ((ThreadPoolTaskExecutor) arg0).setWaitForTasksToCompleteOnShutdown(true);
+ }
+ return arg0;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.beans.factory.config.BeanPostProcessor#
+ * postProcessBeforeInitialization(java .lang.Object, java.lang.String)
+ */
+ @Override
+ public Object postProcessBeforeInitialization(final Object arg0, final String arg1)
+ throws BeansException {
+ return arg0;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.context.ApplicationContextAware#setApplicationContext(org
+ * .springframework. context.ApplicationContext)
+ */
+ @Override
+ public void setApplicationContext(final ApplicationContext arg0) throws BeansException {
+ this.context = arg0;
+
+ }
+
+ private void internalThreadPoolTaskExecutor(final Map<String, ThreadPoolTaskExecutor> executers) {
+ for (final ThreadPoolTaskExecutor executor : executers.values()) {
+ executor.shutdown();
+ log.debug("Executer {} with active {} work has killed", executor.getThreadNamePrefix(),
+ executor.getActiveCount());
+
+ }
+
+ }
+
+ // Not required at the moment
+ private void internalThreadPoolTaskScheduler(
+ final Map<String, ThreadPoolTaskScheduler> schedulers) {
+ log.trace("Stopping #{} task-schedulers", schedulers.size());
+
+ }
+
+ private void internalIDestroyableObject(final Map<String, IDestroyableObject> objectsToDestroy) {
+ if (objectsToDestroy != null) {
+ final Iterator<Entry<String, IDestroyableObject>> interator =
+ objectsToDestroy.entrySet().iterator();
+ while (interator.hasNext()) {
+ final Entry<String, IDestroyableObject> object = interator.next();
+ try {
+ object.getValue().fullyDestroy();
+ log.debug("Object with ID: {} is destroyed", object.getKey());
+
+ } catch (final Exception e) {
+ log.warn("Destroing object with ID: {} FAILED!", object.getKey(), null, e);
+
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java
new file mode 100644
index 00000000..6be1f0ba
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java
@@ -0,0 +1,60 @@
+/*
+ * 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.asitplus.eidas.specific.core.auth;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.idp.slo.ISloInformationContainer;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager;
+import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
+
+@Service("AuthenticationManager")
+public class AuthenticationManager extends AbstractAuthenticationManager {
+ private static final Logger log = LoggerFactory.getLogger(AuthenticationManager.class);
+
+ @Override
+ public ISloInformationContainer performSingleLogOut(HttpServletRequest httpReq,
+ HttpServletResponse httpResp,
+ IRequest pendingReq, String internalSsoId) throws EaafException {
+ throw new RuntimeException("Single LogOut is NOT supported by this implementation");
+
+ }
+
+ @Override
+ protected void populateExecutionContext(ExecutionContext executionContext,
+ RequestImpl pendingReq, HttpServletRequest httpReq)
+ throws EaafException {
+ log.trace("No implementation-specific population of execution-context required ... ");
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java
new file mode 100644
index 00000000..e5937b99
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java
@@ -0,0 +1,255 @@
+/*
+ * 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.asitplus.eidas.specific.core.builder;
+
+import java.util.Date;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.springframework.stereotype.Service;
+
+import com.google.common.collect.Streams;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues;
+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.auth.data.IAuthProcessDataContainer;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData;
+import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData;
+import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper;
+import lombok.extern.slf4j.Slf4j;
+
+@Service("AuthenticationDataBuilder")
+@Slf4j
+public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder {
+
+ private static final String ERROR_B11 = "builder.11";
+
+ @Override
+ protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException {
+ final EidAuthProcessDataWrapper authProcessData =
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class);
+ final EidAuthenticationData authData = new EidAuthenticationData();
+
+ // set basis infos
+ super.generateDeprecatedBasicAuthData(authData, pendingReq, authProcessData);
+
+ // set specific informations
+ authData.setSsoSessionValidTo(
+ new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000));
+
+ authData.setEidStatus(authProcessData.isTestIdentity()
+ ? EidIdentityStatusLevelValues.TESTIDENTITY
+ : EidIdentityStatusLevelValues.IDENTITY);
+
+ return authData;
+
+ }
+
+ @Override
+ protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq)
+ throws EaafException {
+ if (authData instanceof EidAuthenticationData) {
+ ((EidAuthenticationData) authData).setGenericData(
+ ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME,
+ pendingReq.getUniquePiiTransactionIdentifier());
+ log.trace("Inject piiTransactionId: {} into AuthData", pendingReq.getUniquePiiTransactionIdentifier());
+
+ // set specific informations
+ ((EidAuthenticationData) authData).setSsoSessionValidTo(
+ new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000));
+
+ // set E-ID status-level
+ final EidAuthProcessDataWrapper authProcessData =
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class);
+ ((EidAuthenticationData) authData).setEidStatus(authProcessData.isTestIdentity()
+ ? EidIdentityStatusLevelValues.TESTIDENTITY
+ : EidIdentityStatusLevelValues.IDENTITY);
+
+ // handle mandate informations
+ buildMandateInformation((EidAuthenticationData) authData, pendingReq, authProcessData);
+
+ } else {
+ throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: "
+ + authData.getClass().getName());
+
+ }
+
+ }
+
+ @Override
+ protected IAuthData getAuthDataInstance(IRequest arg0) throws EaafException {
+ return new EidAuthenticationData();
+
+ }
+
+ @Override
+ protected Pair<String, String> buildOAspecificbPK(IRequest pendingReq, AuthenticationData authData)
+ throws EaafBuilderException {
+ return super.buildOAspecificbPK(pendingReq, authData);
+
+ }
+
+ @Override
+ protected Pair<String, String> getEncryptedBpkFromPvpAttribute(IAuthProcessDataContainer arg0,
+ AuthenticationData arg1, ISpConfiguration arg2) throws EaafBuilderException {
+ return null;
+
+ }
+
+ @Override
+ protected Pair<String, String> getbaseIdFromSzr(AuthenticationData arg0, String arg1, String arg2) {
+ return null;
+
+ }
+
+ private void buildMandateInformation(EidAuthenticationData authData, IRequest pendingReq,
+ EidAuthProcessDataWrapper authProcessData) throws EaafAuthenticationException, EaafBuilderException,
+ EaafStorageException {
+ authData.setUseMandate(authProcessData.isMandateUsed());
+ if (authProcessData.isMandateUsed()) {
+ log.debug("Build mandate-releated authentication data ... ");
+ if (authProcessData.isForeigner()) {
+ buildMandateInformationForEidasIncoming();
+
+ } else {
+ buildMandateInformationForEidasOutgoing(authData, pendingReq, authProcessData);
+
+ }
+
+ // inject mandate information into authdata
+ final Set<String> mandateAttributes = Streams.concat(
+ MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_NAT_PVP_ATTRIBUTES.stream(),
+ MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_JUR_PVP_ATTRIBUTES.stream())
+ .map(el -> el.getFirst())
+ .collect(Collectors.toSet());
+
+ authProcessData.getGenericSessionDataStream()
+ .filter(el -> mandateAttributes.contains(el.getKey()))
+ .forEach(el -> {
+ try {
+ authData.setGenericData(el.getKey(), el.getValue());
+
+ } catch (final EaafStorageException e) {
+ log.error("Can not store attribute: {} into session.", el.getKey(), e);
+ throw new RuntimeException(e);
+
+ }
+ });
+ }
+ }
+
+ private void buildMandateInformationForEidasIncoming() {
+ log.debug("Find eIDAS incoming process. Generated mandate-information for ID-Austria system ... ");
+
+ // TODO: implement IDA specific processing of foreign mandate
+
+ }
+
+ private void buildMandateInformationForEidasOutgoing(EidAuthenticationData authData, IRequest pendingReq,
+ EidAuthProcessDataWrapper authProcessData) throws EaafAuthenticationException, EaafBuilderException,
+ EaafStorageException {
+ log.debug("Find eIDAS outgoing process. Generated mandate-information for other country ... ");
+ if (authProcessData.getGenericDataFromSession(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME) != null) {
+ final Optional<Triple<String, String, Boolean>> missingAttribute =
+ MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_NAT_PVP_ATTRIBUTES.stream()
+ .filter(el -> authProcessData.getGenericDataFromSession(el.getFirst()) == null)
+ .findFirst();
+ if (missingAttribute.isPresent()) {
+ log.error("ID-Austria response contains not all attributes for nat. person mandator. Missing: {}",
+ missingAttribute.get().getFirst());
+ throw new EaafAuthenticationException(ERROR_B11, new Object[] { "Nat. person mandate" });
+
+ } else {
+ log.trace("Find nat. person mandate. Mandate can be used as it is ");
+ authData.setGenericData(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER,
+ extractBpkFromResponse(authProcessData.getGenericDataFromSession(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, String.class)));
+
+ }
+
+ } else {
+ final Optional<Triple<String, String, Boolean>> missingAttribute =
+ MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_JUR_PVP_ATTRIBUTES.stream()
+ .filter(el -> authProcessData.getGenericDataFromSession(el.getFirst()) == null)
+ .findFirst();
+ if (missingAttribute.isPresent()) {
+ log.error("ID-Austria response contains not all attributes for legal. person mandator. Missing: {}",
+ missingAttribute.get().getFirst());
+ throw new EaafAuthenticationException(ERROR_B11, new Object[] { "Legal. person mandate" });
+
+ } else {
+ log.trace(
+ "Find jur. person mandate. Generate eIDAS identifier from legal-person sourcePin and type ... ");
+ final String sourcePin = authProcessData.getGenericDataFromSession(
+ PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, String.class);
+ final String sourcePinType = authProcessData.getGenericDataFromSession(
+ PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, String.class);
+
+ // build leagl-person identifier for eIDAS out-going
+ final String[] splittedTarget =
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier().split("\\+");
+ StringBuilder sb = new StringBuilder();
+ sb.append(splittedTarget[1])
+ .append("/")
+ .append(splittedTarget[2])
+ .append("/")
+ .append(sourcePinType)
+ .append("+")
+ .append(sourcePin);
+
+ log.debug("Use legal-person eIDAS identifer: {} from baseId: {} and baseIdType: {}",
+ sb.toString(), sourcePin, sourcePinType);
+ authData.setGenericData(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, sb.toString());
+
+ }
+ }
+ }
+
+ private String extractBpkFromResponse(String pvpBpkAttrValue) {
+ final String[] split = pvpBpkAttrValue.split(":", 2);
+ if (split.length == 2) {
+ return split[1];
+
+ } else {
+ log.warn("PVP bPK attribute: {} has wrong format. Use it as it is.", pvpBpkAttrValue);
+ return pvpBpkAttrValue;
+
+ }
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java
new file mode 100644
index 00000000..06377c3f
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2019 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.asitplus.eidas.specific.core.config;
+
+import java.net.MalformedURLException;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.ReloadableResourceBundleMessageSource;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.CookieLocaleResolver;
+import org.thymeleaf.templateresolver.FileTemplateResolver;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+
+/**
+ * Spring configurator for Web resources.
+ *
+ * @author tlenz
+ *
+ */
+@Configuration
+public class StaticResourceConfiguration implements WebMvcConfigurer {
+ private static final Logger log = LoggerFactory.getLogger(StaticResourceConfiguration.class);
+ private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
+ "/"
+ };
+
+ private static final String DEFAULT_MESSAGE_SOURCE = "classpath:properties/status_messages";
+
+ @Autowired
+ private IConfiguration basicConfig;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ final String staticResources = basicConfig.getBasicConfiguration(
+ MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_STATIC_PATH);
+ try {
+ if (StringUtils.isNotEmpty(staticResources)) {
+ String absPath = FileUtils.makeAbsoluteUrl(staticResources, basicConfig
+ .getConfigurationRootDirectory());
+ if (!absPath.endsWith("/")) {
+ absPath += "/";
+ }
+
+ registry.addResourceHandler("/static/**").addResourceLocations(absPath);
+ log.info("Add Ressourcefolder: " + absPath + " for static Web content");
+
+ } else {
+ log.debug("No Ressourcefolder for static Web content");
+ }
+
+ } catch (final MalformedURLException e) {
+ log.warn("Can NOT initialize ressourcefolder for static Web content", e);
+
+ }
+
+ registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
+
+ }
+
+ /**
+ * Get a message source with only internal message properties.
+ *
+ * @param ressourceLocations List of source-locations
+ * @return
+ */
+ @Bean
+ public ReloadableResourceBundleMessageSource internalMessageSource(
+ @Autowired(required = false) final List<IMessageSourceLocation> ressourceLocations) {
+ final ReloadableResourceBundleMessageSource messageSource =
+ new ReloadableResourceBundleMessageSource();
+
+ // add default message source
+ messageSource.setBasename(DEFAULT_MESSAGE_SOURCE);
+
+ if (ressourceLocations != null) {
+ // load more message sources
+ for (final IMessageSourceLocation el : ressourceLocations) {
+ if (el.getMessageSourceLocation() != null) {
+ for (final String source : el.getMessageSourceLocation()) {
+ messageSource.addBasenames(source);
+ log.debug("Add additional messageSources: {}", el.getMessageSourceLocation().toArray());
+
+ }
+ }
+ }
+ }
+
+ messageSource.setDefaultEncoding("UTF-8");
+ return messageSource;
+
+ }
+
+ /**
+ * Get full message source with internal and external message-properties files.
+ *
+ * @param ressourceLocations List of source-locations
+ * @return
+ */
+ @Bean
+ public ReloadableResourceBundleMessageSource messageSource(
+ @Autowired(required = false) final List<IMessageSourceLocation> ressourceLocations) {
+ final ReloadableResourceBundleMessageSource messageSource =
+ new ReloadableResourceBundleMessageSource();
+ messageSource.setDefaultEncoding("UTF-8");
+ messageSource.setParentMessageSource(internalMessageSource(ressourceLocations));
+
+ final String staticResources = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_PROPERTIES_PATH);
+ try {
+ if (StringUtils.isNotEmpty(staticResources)) {
+ final String absPath =
+ FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory());
+ messageSource.setBasename(absPath);
+
+ } else {
+ log.debug("No Ressourcefolder for dynamic Web content templates");
+
+ }
+
+ } catch (final MalformedURLException e) {
+ log.warn("Can NOT initialize ressourcefolder for dynamic Web content templates", e);
+
+ }
+
+ return messageSource;
+
+ }
+
+ /**
+ * Get a i18n resolver based on cookies.
+ *
+ * @return
+ */
+ @Bean
+ public CookieLocaleResolver localeResolver() {
+ final CookieLocaleResolver localeResolver = new CookieLocaleResolver();
+ localeResolver.setCookieName("currentLanguage");
+ localeResolver.setCookieMaxAge(3600);
+ return localeResolver;
+
+ }
+
+ /**
+ * Get a Tyhmeleaf Template-Resolver with external configuration path.
+ *
+ * @return
+ */
+ @Bean(name = "templateResolver")
+ public FileTemplateResolver templateResolver() {
+ final String staticResources = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_PATH);
+ try {
+ if (StringUtils.isNotEmpty(staticResources)) {
+ String absPath =
+ FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory());
+ if (!absPath.endsWith("/")) {
+ absPath += "/";
+
+ }
+
+ if (absPath.startsWith("file:")) {
+ absPath = absPath.substring("file:".length());
+
+ }
+
+ final FileTemplateResolver viewResolver = new FileTemplateResolver();
+ viewResolver.setPrefix(absPath);
+ viewResolver.setSuffix(".html");
+ viewResolver.setTemplateMode("HTML");
+ viewResolver.setCacheable(false);
+
+ log.info("Add Ressourcefolder: {} for dynamic Web content templates", absPath);
+ return viewResolver;
+
+ } else {
+ log.debug("No Ressourcefolder for dynamic Web content templates");
+
+ }
+
+ } catch (final MalformedURLException e) {
+ log.warn("Can NOT initialize ressourcefolder for dynamic Web content templates", e);
+
+ }
+
+ throw new RuntimeException("Can NOT initialize HTML template resolver");
+
+ }
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java
new file mode 100644
index 00000000..754fe9ab
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java
@@ -0,0 +1,69 @@
+package at.asitplus.eidas.specific.core.health;
+
+import java.io.ByteArrayInputStream;
+
+import javax.xml.transform.TransformerFactoryConfigurationError;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.StatusLine;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.core.impl.http.HttpUtils;
+import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EidasNodeMetadataHealthIndicator implements HealthIndicator {
+
+ @Autowired IConfiguration config;
+ @Autowired IHttpClientFactory httpClientFactory;
+
+ @Override
+ public Health health() {
+ try {
+ final String urlString = config.getBasicConfiguration(
+ MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL);
+ if (StringUtils.isEmpty(urlString)) {
+ log.trace("No eIDASNode metadata URL. Skipping test ... ");
+ return Health.unknown().build();
+
+ }
+
+ // create HTTP client
+ CloseableHttpClient httpClient = httpClientFactory.getHttpClient();
+ URIBuilder uriBuilder = new URIBuilder(urlString);
+ HttpUriRequest request = new HttpGet(uriBuilder.build());
+
+ final Triple<StatusLine, ByteArrayInputStream, ContentType> respCode = httpClient.execute(request,
+ HttpUtils.bodyStatusCodeResponseHandler());
+ if (respCode.getFirst().getStatusCode() != 200) {
+ log.warn("Monitoring: Get http StatusCode: {} from eIDAS-Node Metadata endpoint",
+ respCode.getFirst().getStatusCode());
+ return Health.down().withDetail("http StatusCode", respCode.getFirst().getStatusCode()).build();
+
+ }
+
+ // parse metadata
+ DomUtils.parseXmlNonValidating(respCode.getSecond());
+
+ return Health.up().build();
+
+ } catch (Exception | TransformerFactoryConfigurationError e) {
+ log.warn("Monitoring: Can not read SAML2 metadata from eIDAS-Node", e);
+ return Health.down().down(e).build();
+
+ }
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java
new file mode 100644
index 00000000..651f9125
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java
@@ -0,0 +1,52 @@
+package at.asitplus.eidas.specific.core.health;
+
+import org.apache.ignite.Ignite;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+
+import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * HealthCheck that validate Nodes in Apache-Ignite Cluster.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class IgniteClusterHealthIndicator implements HealthIndicator {
+
+ @Setter
+ protected IgniteInstanceInitializerSpecificCommunication igniteInstanceInitializerSpecificCommunication;
+
+ @Override
+ public Health health() {
+ final Ignite instance = igniteInstanceInitializerSpecificCommunication.getInstance();
+
+ // check if Apache Ignite cluster is active
+ if (!instance.cluster().active()) {
+ return Health.outOfService().build();
+
+ }
+
+ final Health.Builder healthBuilder;
+ // Status UP requires more than 1 node because MS-Connector and eIDAS-Node operations as
+ // micro-services
+ if (instance.cluster().nodes().size() > 1) {
+ healthBuilder = Health.up();
+
+ } else {
+ // Something looks wrong if only a single node was found because MS-Connector and eIDAS-Node
+ // operations as micro-services
+ healthBuilder = Health.outOfService();
+
+ }
+
+ healthBuilder.withDetail("#Nodes", instance.cluster().nodes().size());
+ log.trace("Ignite state. #Nodes: {}", instance.cluster().nodes().size());
+ return healthBuilder.build();
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java
new file mode 100644
index 00000000..f665be51
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java
@@ -0,0 +1,90 @@
+/*
+ * 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.asitplus.eidas.specific.core.interceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * Spring interceptor to inject securtiy headers into http response.
+ *
+ * @author tlenz
+ *
+ */
+public class WebFrontEndSecurityInterceptor implements HandlerInterceptor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.
+ * http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
+ * java.lang.Object)
+ */
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+
+ // set security headers
+ response.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT");
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-control", "no-store, no-cache, must-revalidate");
+
+ return true;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.
+ * http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
+ * java.lang.Object, org.springframework.web.servlet.ModelAndView)
+ */
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+ ModelAndView modelAndView) throws Exception {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.
+ * servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
+ * java.lang.Object, java.lang.Exception)
+ */
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
+ Exception ex)
+ throws Exception {
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java
new file mode 100644
index 00000000..03a56976
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java
@@ -0,0 +1,110 @@
+/*
+ * 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.asitplus.eidas.specific.core.logger;
+
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.components.eventlog.api.Event;
+import at.gv.egiz.components.eventlog.api.EventConstants;
+import at.gv.egiz.components.eventlog.api.EventLogFactory;
+import at.gv.egiz.components.eventlog.api.EventLoggingException;
+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.logging.IRevisionLogger;
+
+public class RevisionLogger extends EventLogFactory implements IRevisionLogger {
+ private static final Logger log = LoggerFactory.getLogger(RevisionLogger.class);
+
+ @Autowired
+ private IConfiguration basicConfig;
+
+ @Override
+ public void logEvent(ISpConfiguration oaConfig, int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message));
+
+ }
+
+ @Override
+ public void logEvent(IRequest pendingRequest, int eventCode) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode,
+ pendingRequest.getUniqueSessionIdentifier(), pendingRequest.getUniqueTransactionIdentifier()));
+
+ }
+
+ @Override
+ public void logEvent(IRequest pendingRequest, int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message,
+ pendingRequest.getUniqueSessionIdentifier(), pendingRequest.getUniqueTransactionIdentifier()));
+
+ }
+
+ @Override
+ public void logEvent(int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message));
+
+ }
+
+ @Override
+ public void logEvent(String sessionID, String transactionID, int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message, sessionID, transactionID));
+
+ }
+
+ @Override
+ public void logEvent(String sessionID, String transactionID, int eventCode) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, sessionID, transactionID));
+
+ }
+
+ private void logEvent(Event event) {
+ try {
+ if (event.getEventCode() >= 1100) {
+ if (event.getEventCode() == EventConstants.TRANSACTION_IP
+ && !basicConfig.getBasicConfigurationBoolean(
+ MsEidasNodeConstants.PROP_CONFIG_REVISIONLOG_LOG_IP_ADDRESS_OF_USER, true)) {
+ log.trace("Ignore Event: " + event.getEventCode() + " because IP adresse logging prohibited");
+ return;
+
+ }
+
+ getEventLog().logEvent(event);
+
+ } else {
+ log.trace("Ignore Event: " + event.getEventCode()
+ + " because session functionallity is not implemented");
+ }
+
+ } catch (final EventLoggingException e) {
+ log.warn("Event logging FAILED! Reason: " + e.getMessage());
+
+ }
+
+ }
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java
new file mode 100644
index 00000000..bdaf83f6
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java
@@ -0,0 +1,141 @@
+/*
+ * 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.asitplus.eidas.specific.core.logger;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+public class StatisticLogger implements IStatisticLogger {
+
+ private static final Logger log = LoggerFactory.getLogger(StatisticLogger.class);
+
+ private static final String DATEFORMATER = "yyyy.MM.dd-HH:mm:ss+z";
+ private static final String STATUS_SUCCESS = "success";
+ private static final String STATUS_ERROR = "error";
+
+ @Override
+ public void logSuccessOperation(IRequest protocolRequest, IAuthData authData, boolean isSsoSession) {
+ log.info(buildLogMessage(
+ protocolRequest.getUniqueTransactionIdentifier(),
+ protocolRequest.getSpEntityId(),
+ protocolRequest.getRawData(MsEidasNodeConstants.DATA_REQUESTERID),
+ protocolRequest.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(),
+ authData.getCiticenCountryCode(),
+ STATUS_SUCCESS,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY));
+
+ }
+
+ @Override
+ public void logErrorOperation(Throwable throwable) {
+ String errorId = "TODO";
+ if (throwable instanceof EaafException) {
+ errorId = ((EaafException) throwable).getErrorId();
+ }
+
+ log.info(buildLogMessage(
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ STATUS_ERROR,
+ errorId,
+ throwable.getMessage()));
+
+ }
+
+ @Override
+ public void logErrorOperation(Throwable throwable, IRequest errorRequest) {
+ String errorId = "TODO";
+ if (throwable instanceof EaafException) {
+ errorId = ((EaafException) throwable).getErrorId();
+ }
+
+ if (errorRequest != null) {
+ log.info(buildLogMessage(
+ errorRequest.getUniqueTransactionIdentifier(),
+ errorRequest.getSpEntityId(),
+ errorRequest.getRawData(MsEidasNodeConstants.DATA_REQUESTERID),
+ errorRequest.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(),
+ StringUtils.EMPTY,
+ STATUS_ERROR,
+ errorId,
+ throwable.getMessage()));
+ } else {
+ log.info(buildLogMessage(
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ STATUS_ERROR,
+ errorId,
+ throwable.getMessage()));
+ }
+
+ }
+
+ @Override
+ public void internalTesting() throws Exception {
+ log.trace("Not implemented for a File-based logger");
+
+ }
+
+ private String buildLogMessage(String transId, String entityId, Object requesterId, String target,
+ String cc,
+ String status, String errorCode, String errorMsg) {
+ String logMsg = StringUtils.EMPTY;
+
+ // data,tId,MOAID-Id,SP-Id,bPKTarget,CC,status,error-code,error-msg
+
+ logMsg += DateTime.now().toString(DATEFORMATER) + ",";
+ logMsg += transId + ",";
+ logMsg += entityId + ",";
+
+ if (requesterId instanceof String && StringUtils.isNotEmpty((String) requesterId)) {
+ logMsg += (String) requesterId + ",";
+ } else {
+ logMsg += StringUtils.EMPTY + ",";
+ }
+
+ logMsg += target + ",";
+ logMsg += cc + ",";
+
+ logMsg += status + ",";
+ logMsg += errorCode + ",";
+ logMsg += errorMsg;
+
+ return logMsg;
+ }
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java
new file mode 100644
index 00000000..e3ab5d45
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java
@@ -0,0 +1,60 @@
+/*
+ * 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.asitplus.eidas.specific.core.mapper;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper;
+
+@Service("LoALevelMapper")
+public class LoALevelMapper implements ILoALevelMapper {
+ private static final Logger log = LoggerFactory.getLogger(LoALevelMapper.class);
+
+ @Override
+ public String mapToSecClass(String loa) {
+ log.info("Mapping to PVP SecClass is NOT supported");
+ return null;
+ }
+
+ @Override
+ public String mapToEidasLoa(String loa) {
+ if (loa.startsWith(EaafConstants.EIDAS_LOA_PREFIX)) {
+ return loa;
+ } else {
+ log.info("Can NOT map '" + loa + "' to eIDAS LoA");
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public String mapEidasQaaToStorkQaa(String eidasqaaLevel) {
+ return null;
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java
new file mode 100644
index 00000000..b47c0b63
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java
@@ -0,0 +1,182 @@
+/*
+ * 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.asitplus.eidas.specific.core.provider;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IStatusMessenger;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory;
+
+@Service("StatusMessageProvider")
+public class StatusMessageProvider implements IStatusMessenger, MessageSourceAware {
+ private static final Logger log = LoggerFactory.getLogger(StatusMessageProvider.class);
+
+ private static final String ERROR_MESSAGES_UNAVAILABLE =
+ "Error messages can NOT be load from application. Only errorCode: {0} is availabe";
+ private static final String ERROR_NO_MESSAGE = "No errormesseage for error with number.={0}";
+
+ private static final String ERROR_EXTERNALERROR_CODES_UNAVAILABLE =
+ "External error-codes can NOT be load from application. Only internal errorCode: {0} is availabe";
+ private static final String ERROR_NO_EXTERNALERROR_CODE =
+ "No external error for internal error with number.={0}";
+ private static final String MSG_WARN_NO_SOURCE = "MessageCode: {} is NOT SET for locale: {}";
+ private static final String MSG_INFO = "Use locale: {} as default";
+
+ // external error codes
+ private static final String DEFAULT_EXTERNALERROR_RESOURCES = "properties/external_statuscodes_map";
+ private static final Locale DEFAULT_EXTERNALERROR_LOCALES = new Locale("en", "GB");
+ private ResourceBundle externalError = null;
+
+ //internal messanges
+ private MessageSource messageSource;
+
+ @Override
+ public String getMessageWithoutDefault(final String messageId, final Object[] parameters) {
+ if (messageSource == null) {
+ return null;
+
+ } else {
+ try {
+ final Locale locale = LocaleContextHolder.getLocale();
+ return messageSource.getMessage(messageId, parameters, locale);
+
+ } catch (final NoSuchMessageException e) {
+ log.info(MSG_WARN_NO_SOURCE, messageId, LocaleContextHolder.getLocale());
+ log.debug(MSG_INFO, Locale.ENGLISH);
+
+ try {
+ return messageSource.getMessage(messageId, parameters, Locale.ENGLISH);
+
+ } catch (final NoSuchMessageException e2) {
+ log.info(MSG_WARN_NO_SOURCE, messageId, Locale.ENGLISH);
+
+ }
+
+ } catch (final MissingResourceException e2) {
+ log.warn("No message source", e2);
+
+ }
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public String getMessage(final String messageId, final Object[] parameters) {
+ if (messageSource == null) {
+ return MessageFormat.format(ERROR_MESSAGES_UNAVAILABLE, new Object[]{messageId});
+
+ } else {
+ try {
+ final Locale locale = LocaleContextHolder.getLocale();
+ return messageSource.getMessage(messageId, parameters, locale);
+
+ } catch (final NoSuchMessageException e) {
+ log.info(MSG_WARN_NO_SOURCE, messageId, LocaleContextHolder.getLocale());
+ log.debug(MSG_INFO, Locale.ENGLISH);
+
+ try {
+ return messageSource.getMessage(messageId, parameters, Locale.ENGLISH);
+
+ } catch (final NoSuchMessageException e2) {
+ return MessageFormat.format(ERROR_NO_MESSAGE, new Object[]{messageId});
+
+ }
+
+ } catch (final MissingResourceException e2) {
+ return MessageFormat.format(ERROR_NO_MESSAGE, new Object[]{messageId});
+
+ }
+ }
+ }
+
+ @Override
+ public String getResponseErrorCode(Throwable throwable) {
+ String errorCode = IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+ if (throwable instanceof EaafException) {
+ errorCode = ((EaafException) throwable).getErrorId();
+
+ }
+
+ return errorCode;
+
+ }
+
+ @Override
+ public String mapInternalErrorToExternalError(String intErrorCode) {
+ // initialize messages
+ if (externalError == null) {
+ this.externalError = ResourceBundle.getBundle(
+ DEFAULT_EXTERNALERROR_RESOURCES,
+ DEFAULT_EXTERNALERROR_LOCALES);
+
+ }
+
+ // create the message
+ if (externalError == null) {
+ log.warn(MessageFormat.format(ERROR_EXTERNALERROR_CODES_UNAVAILABLE, new Object[] { intErrorCode }));
+ return IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+
+ } else {
+ try {
+ if (StringUtils.isNotEmpty(intErrorCode)) {
+ return externalError.getString(intErrorCode);
+
+ } else {
+ return IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+
+ }
+
+ } catch (final MissingResourceException e2) {
+ log.info(MessageFormat.format(ERROR_NO_EXTERNALERROR_CODE, new Object[] { intErrorCode }));
+ return IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+
+ }
+ }
+ }
+
+ @Override
+ public void setMessageSource(MessageSource messageSource) {
+ this.messageSource = messageSource;
+
+ log.info("Injecting 'StatusMessanger' into 'LogMessageProviderFactory'");
+ LogMessageProviderFactory.setStatusMessager(this);
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java
new file mode 100644
index 00000000..0eeb35d9
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java
@@ -0,0 +1,35 @@
+/*
+ * 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.asitplus.eidas.specific.core.storage;
+
+import eu.eidas.auth.commons.cache.ConcurrentCacheService;
+import eu.eidas.auth.commons.tx.AbstractCache;
+
+public class CacheWithEidasBackend extends AbstractCache<String, TransactionStoreElement> {
+
+ protected CacheWithEidasBackend(ConcurrentCacheService concurrentMapService) {
+ super(concurrentMapService);
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java
new file mode 100644
index 00000000..5a59a4e0
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java
@@ -0,0 +1,180 @@
+/*
+ * 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.asitplus.eidas.specific.core.storage;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+
+public class EidasCacheTransactionStoreDecorator implements ITransactionStorage, HealthIndicator {
+ private static final Logger log = LoggerFactory.getLogger(EidasCacheTransactionStoreDecorator.class);
+
+ @Autowired(required = true)
+ private CacheWithEidasBackend storage;
+
+ @Override
+ public Health health() {
+ try {
+ final String key = Random.nextHexRandom16();
+ final String value = Random.nextHexRandom16();
+
+ this.put(key, value, -1);
+ final String result = this.get(key, String.class);
+ this.remove(key);
+
+ if (result != null && result.equals(value)) {
+ return Health.up().build();
+
+ } else {
+ log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test");
+ return Health.down().build();
+
+ }
+
+ } catch (final EaafException e) {
+ log.warn("Montioring: Can not read/write to storage.", e);
+ return Health.down().down(e).build();
+
+ }
+ }
+
+ @Override
+ public void changeKey(String oldKey, String newKey, Object value) throws EaafException {
+ if (containsKey(oldKey)) {
+ final TransactionStoreElement el = storage.get(oldKey);
+ el.setKey(newKey);
+ el.setData(value);
+ storage.put(newKey, el);
+ boolean delResult = storage.remove(oldKey);
+ log.trace("Object: {} removed from cache: {}", oldKey, delResult);
+
+ } else {
+ throw new EaafStorageException("No element in TransactionStorage with key: " + oldKey);
+ }
+
+ }
+
+ @Override
+ public List<String> clean(Date now, long dataTimeOut) {
+ log.info("Clean is NOT implemented, because its not needed");
+ return Arrays.asList();
+
+ }
+
+ @Override
+ public boolean containsKey(String key) {
+ return storage.containsKey(key);
+
+ }
+
+ @Override
+ public Object get(String key) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement element = storage.get(key);
+ return element.getData();
+
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public <T> T get(String key, Class<T> type) throws EaafException {
+ return get(key, type, -1);
+
+ }
+
+ @Override
+ public <T> T get(String key, Class<T> type, long dataTimeOut) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement value = storage.get(key);
+
+ if (dataTimeOut > -1) {
+ final long now = new Date().getTime();
+ if (now - value.getCreated().getTime() > dataTimeOut) {
+ log.info("Transaction-Data with key: " + key + " is out of time.");
+ throw new EaafStorageException("Transaction-Data with key: " + key + " is out of time.");
+
+ }
+ }
+
+ if (type.isAssignableFrom(value.getData().getClass())) {
+ return (T) value.getData();
+
+ } else {
+ log.warn("Can NOT cast '" + value.getClass() + "' to '" + type + "'");
+ }
+
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object getRaw(String key) throws EaafException {
+ return storage.get(key);
+
+ }
+
+ @Override
+ public void put(String key, Object value, int dataTimeOut) throws EaafException {
+ final TransactionStoreElement element = new TransactionStoreElement();
+ element.setKey(key);
+ element.setData(value);
+ storage.put(key, element);
+
+ }
+
+ @Override
+ public void putRaw(String key, Object value) throws EaafException {
+ if (value instanceof TransactionStoreElement) {
+ storage.put(((TransactionStoreElement) value).getKey(), (TransactionStoreElement) value);
+ } else {
+ log.info(value.getClass().getName() + " is NOT a RAW element of " + ITransactionStorage.class
+ .getName());
+ }
+
+ }
+
+ @Override
+ public void remove(String key) {
+ if (containsKey(key)) {
+ log.trace("Remove element with key: " + key + " from " + ITransactionStorage.class.getName());
+ boolean delResult = storage.remove(key);
+ log.trace("Object: {} removed from cache: {}", key, delResult);
+
+ }
+ }
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java
new file mode 100644
index 00000000..a3a8af0f
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java
@@ -0,0 +1,169 @@
+/*
+ * 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.asitplus.eidas.specific.core.storage;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+
+public class SimpleInMemoryTransactionStorage implements ITransactionStorage {
+ private static final Logger log = LoggerFactory.getLogger(SimpleInMemoryTransactionStorage.class);
+
+ private final Map<String, TransactionStoreElement> storage =
+ new ConcurrentHashMap<>();
+
+ @Override
+ public void changeKey(String oldKey, String newKey, Object value) throws EaafException {
+ if (containsKey(oldKey)) {
+ final TransactionStoreElement el = storage.get(oldKey);
+ el.setKey(newKey);
+ storage.put(newKey, el);
+ storage.remove(oldKey);
+
+ } else {
+ throw new EaafStorageException("No element in TransactionStorage with key: " + oldKey);
+ }
+
+ }
+
+ @Override
+ public List<String> clean(Date now, long dataTimeOut) {
+ final List<String> result = new ArrayList<>();
+ final Iterator<Entry<String, TransactionStoreElement>> iterator = storage.entrySet().iterator();
+ while (iterator.hasNext()) {
+ final Entry<String, TransactionStoreElement> key = iterator.next();
+ synchronized (storage) {
+ if (storage.containsKey(key.getKey())) {
+ final TransactionStoreElement element = key.getValue();
+ if (now.getTime() - element.getCreated().getTime() > dataTimeOut) {
+ result.add(key.getKey());
+ }
+ }
+ }
+ }
+
+ return result;
+
+ }
+
+ @Override
+ public boolean containsKey(String key) {
+ if (key != null) {
+ return storage.containsKey(key);
+ } else {
+ return false;
+ }
+
+ }
+
+ @Override
+ public Object get(String key) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement element = storage.get(key);
+ return element.getData();
+
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public <T> T get(String key, Class<T> type) throws EaafException {
+ return get(key, type, -1);
+
+ }
+
+ @Override
+ public <T> T get(String key, Class<T> type, long dataTimeOut) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement value = storage.get(key);
+
+ if (dataTimeOut > -1) {
+ final long now = new Date().getTime();
+ if (now - value.getCreated().getTime() > dataTimeOut) {
+ log.info("Transaction-Data with key: " + key + " is out of time.");
+ throw new EaafStorageException("Transaction-Data with key: " + key + " is out of time.");
+
+ }
+ }
+
+ if (type.isAssignableFrom(value.getData().getClass())) {
+ return (T) value.getData();
+
+ } else {
+ log.warn("Can NOT cast '" + value.getClass() + "' to '" + type + "'");
+ }
+
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object getRaw(String key) throws EaafException {
+ return storage.get(key);
+
+ }
+
+ @Override
+ public void put(String key, Object value, int dataTimeOut) throws EaafException {
+ final TransactionStoreElement element = new TransactionStoreElement();
+ element.setKey(key);
+ element.setData(value);
+ storage.put(key, element);
+
+ }
+
+ @Override
+ public void putRaw(String key, Object value) throws EaafException {
+ if (value instanceof TransactionStoreElement) {
+ storage.put(((TransactionStoreElement) value).getKey(), (TransactionStoreElement) value);
+ } else {
+ log.info(value.getClass().getName() + " is NOT a RAW element of " + ITransactionStorage.class
+ .getName());
+ }
+
+ }
+
+ @Override
+ public void remove(String key) {
+ if (containsKey(key)) {
+ log.debug("Remove element with key: " + key + " from " + ITransactionStorage.class.getName());
+ storage.remove(key);
+
+ }
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java
new file mode 100644
index 00000000..48668d4b
--- /dev/null
+++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java
@@ -0,0 +1,70 @@
+/*
+ * 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.asitplus.eidas.specific.core.storage;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class TransactionStoreElement implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private String key = null;
+ private Object data = null;
+ private Date created;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public Date getCreated() {
+ return copyOrNull(created);
+ }
+
+ public void setCreated(Date created) {
+ this.created = copyOrNull(created);
+ }
+
+ private Date copyOrNull(Date in) {
+ if (in != null) {
+ return new Date(in.getTime());
+
+ }
+
+ return null;
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml b/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml
new file mode 100644
index 00000000..f37dc451
--- /dev/null
+++ b/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml
@@ -0,0 +1,61 @@
+<?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"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ 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
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+ <import resource="common_gui.beans.xml"/>
+ <import resource="classpath:specific_eIDAS_core_storage.beans.xml"/>
+
+ <bean id="WebResourceConfiguration"
+ class="at.asitplus.eidas.specific.core.config.StaticResourceConfiguration" />
+
+ <bean id="eidasNodeMetadata"
+ class="at.asitplus.eidas.specific.core.health.EidasNodeMetadataHealthIndicator" />
+
+ <bean id="AuthenticationManager"
+ class="at.asitplus.eidas.specific.core.auth.AuthenticationManager" />
+
+ <bean id="AuthenticationDataBuilder"
+ class="at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder" />
+
+ <bean id="eaafProtocolAuthenticationService"
+ class="at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService">
+ <property name="guiBuilder" ref="mvcGUIBuilderImpl" />
+ </bean>
+
+ <bean id="securePendingRequestIdGeneration"
+ class="at.gv.egiz.eaaf.core.impl.utils.SecurePendingRequestIdGenerationStrategy" />
+
+ <bean id="LoALevelMapper"
+ class="at.asitplus.eidas.specific.core.mapper.LoALevelMapper" />
+
+ <bean id="GUIBuilderConfigurationFactory"
+ class="at.asitplus.eidas.specific.core.gui.GuiBuilderConfigurationFactory" />
+
+ <bean id="velocityGUIBuilderImpl"
+ class="at.asitplus.eidas.specific.core.gui.DefaultVelocityGuiBuilderImpl" />
+
+ <bean id="mvcGUIBuilderImpl"
+ class="at.gv.egiz.eaaf.core.impl.gui.builder.SpringMvcGuiFormBuilderImpl" />
+
+ <bean id="StatusMessageProvider"
+ class="at.asitplus.eidas.specific.core.provider.StatusMessageProvider" />
+
+ <bean id="eidasRevisionLogger"
+ class="at.asitplus.eidas.specific.core.logger.RevisionLogger" />
+
+ <bean id="eidasStatisticLogger"
+ class="at.asitplus.eidas.specific.core.logger.StatisticLogger" />
+
+ <bean id="defaultErrorHandler"
+ class="at.gv.egiz.eaaf.core.impl.idp.auth.services.DefaultErrorService"/>
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml b/modules/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml
new file mode 100644
index 00000000..259f5605
--- /dev/null
+++ b/modules/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml
@@ -0,0 +1,39 @@
+<?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"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ 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
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+ <import
+ resource="classpath:specificCommunicationDefinitionApplicationContext.xml" />
+
+ <!-- <bean id="SimpleInMemoryTransactionStorage" class="at.asitplus.eidas.specific.connector.storage.SimpleInMemoryTransactionStorage"
+ /> -->
+
+ <bean id="eIDASCacheTransactionStoreDecorator"
+ class="at.asitplus.eidas.specific.core.storage.EidasCacheTransactionStoreDecorator" />
+
+ <bean id="CacheWitheIDASBackend"
+ class="at.asitplus.eidas.specific.core.storage.CacheWithEidasBackend">
+ <constructor-arg ref="msNodeCacheImpl" />
+ </bean>
+
+ <bean id="msNodeCacheImpl"
+ class="eu.eidas.auth.cache.ConcurrentCacheServiceIgniteSpecificCommunicationImpl">
+ <property name="igniteInstanceInitializerSpecificCommunication" ref="eidasIgniteInstanceInitializerSpecificCommunication" />
+ <property name="cacheName" value="msConnectorCache" />
+ </bean>
+
+ <bean id="IgniteClusterState"
+ class="at.asitplus.eidas.specific.core.health.IgniteClusterHealthIndicator">
+ <property name="igniteInstanceInitializerSpecificCommunication" ref="eidasIgniteInstanceInitializerSpecificCommunication" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java
new file mode 100644
index 00000000..06ce8abe
--- /dev/null
+++ b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java
@@ -0,0 +1,70 @@
+package at.asitplus.eidas.specific.core.test.health;
+
+import java.io.IOException;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+import at.asitplus.eidas.specific.core.health.EidasNodeMetadataHealthIndicator;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({
+ "/spring/SpringTest-context_healthcheck.xml" })
+@TestPropertySource(locations = {"classpath:/config/junit_config_2_springboot.properties"})
+@WebAppConfiguration
+public class EidasNodeMetadataHealthIndicatorNoEndpointTest {
+
+ @Autowired EidasNodeMetadataHealthIndicator health;
+
+ private static MockWebServer mockWebServer = null;
+
+ /**
+ * Testclass initializer.
+ *
+ * @throws IOException In case of an error
+ */
+ @BeforeClass
+ public static void classInitializer() throws IOException {
+ mockWebServer = new MockWebServer();
+ mockWebServer.start(40900);
+ mockWebServer.url("/mockup");
+
+ }
+
+ @AfterClass
+ public static void resetTestEnviroment() throws NoSuchFieldException, SecurityException,
+ IllegalArgumentException, IllegalAccessException, IOException {
+ mockWebServer.shutdown();
+
+ }
+
+ @Test
+ public void noEndpointInConfiguration() throws IOException {
+ //set-up status
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorNoEndpointTest.class
+ .getResourceAsStream("/config/log4j.properties"), "UTF-8"))
+ .setHeader("Content-Type", MediaType.APPLICATION_XML));
+
+ //perform test
+ Health status = health.health();
+
+ //validate state
+ Assert.assertEquals("wrong healthState", Health.unknown().build().getStatus(), status.getStatus());
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java
new file mode 100644
index 00000000..e8bc7817
--- /dev/null
+++ b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java
@@ -0,0 +1,102 @@
+package at.asitplus.eidas.specific.core.test.health;
+
+import java.io.IOException;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+import at.asitplus.eidas.specific.core.health.EidasNodeMetadataHealthIndicator;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({
+ "/spring/SpringTest-context_healthcheck.xml" })
+@TestPropertySource(locations = {"classpath:/config/junit_config_1_springboot.properties"})
+@WebAppConfiguration
+public class EidasNodeMetadataHealthIndicatorTest {
+
+ @Autowired EidasNodeMetadataHealthIndicator health;
+
+ private static MockWebServer mockWebServer = null;
+
+ /**
+ * Testclass initializer.
+ *
+ * @throws IOException In case of an error
+ */
+ @BeforeClass
+ public static void classInitializer() throws IOException {
+ mockWebServer = new MockWebServer();
+ mockWebServer.start(40900);
+ mockWebServer.url("/mockup");
+
+ }
+
+ @AfterClass
+ public static void resetTestEnviroment() throws NoSuchFieldException, SecurityException,
+ IllegalArgumentException, IllegalAccessException, IOException {
+ mockWebServer.shutdown();
+
+ }
+
+ @Test
+ public void httpStatusCode500() throws IOException {
+ //set-up status
+ mockWebServer.enqueue(new MockResponse().setResponseCode(500)
+ .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class
+ .getResourceAsStream("/data/metadata_valid.xml"), "UTF-8"))
+ .setHeader("Content-Type", MediaType.APPLICATION_XML));
+
+ //perform test
+ Health status = health.health();
+
+ //validate state
+ Assert.assertEquals("wrong healthState", Health.down().build().getStatus(), status.getStatus());
+
+ }
+
+ @Test
+ public void httpStatusCode200() throws IOException {
+ //set-up status
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class
+ .getResourceAsStream("/data/metadata_valid.xml"), "UTF-8"))
+ .setHeader("Content-Type", MediaType.APPLICATION_XML));
+
+ //perform test
+ Health status = health.health();
+
+ //validate state
+ Assert.assertEquals("wrong healthState", Health.up().build().getStatus(), status.getStatus());
+
+ }
+
+ @Test
+ public void noXmlResponse() throws IOException {
+ //set-up status
+ mockWebServer.enqueue(new MockResponse().setResponseCode(200)
+ .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class
+ .getResourceAsStream("/config/log4j.properties"), "UTF-8"))
+ .setHeader("Content-Type", MediaType.APPLICATION_XML));
+
+ //perform test
+ Health status = health.health();
+
+ //validate state
+ Assert.assertEquals("wrong healthState", Health.down().build().getStatus(), status.getStatus());
+
+ }
+
+}
diff --git a/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java
new file mode 100644
index 00000000..586749cb
--- /dev/null
+++ b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java
@@ -0,0 +1,635 @@
+package at.asitplus.eidas.specific.core.test.utils;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.security.PublicKey;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.config.InitializationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.w3c.dom.Element;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues;
+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.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafParserException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder;
+import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/SpringTest_core_config.beans.xml", "/spring/SpringTest_core.beans.xml", "/eaaf_core.beans.xml",
+ "/eaaf_pvp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" })
+@ActiveProfiles(profiles = {"deprecatedConfig"})
+@WebAppConfiguration
+public class AuthenticationDataBuilderTest {
+
+ @Autowired
+ private AuthenticationDataBuilder authenticationDataBuilder;
+
+ @Autowired(required = true)
+ private IConfiguration basicConfig;
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+
+ private DummySpConfiguration oaParam;
+ private Map<String, String> spConfig;
+
+ private String eidasBind;
+ private String authBlock;
+
+ @BeforeClass
+ public static void classInitializer() throws InitializationException, ComponentInitializationException {
+ final String current = new java.io.File(".").toURI().toString();
+ System.setProperty("eidas.ms.configuration", current
+ + "src/test/resources/config/junit_config_3.properties");
+
+ EaafOpenSaml3xInitializer.eaafInitialize();
+ }
+
+ @Before
+ public void initialize() throws EaafStorageException {
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+
+ pendingReq = new TestRequestImpl();
+ pendingReq.setAuthUrl("https://localhost/ms_connector");
+ pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setSpConfig(oaParam);
+ authBlock = RandomStringUtils.randomAlphanumeric(20);
+ eidasBind = RandomStringUtils.randomAlphanumeric(20);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setQaaLevel(EaafConstants.EIDAS_LOA_PREFIX + RandomStringUtils.randomAlphabetic(5));
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession(
+ PvpAttributeDefinitions.EID_ISSUING_NATION_NAME,
+ RandomStringUtils.randomAlphabetic(2).toUpperCase());
+
+ LocaleContextHolder.resetLocaleContext();
+
+ }
+
+ @Test
+ public void eidasProxyMode() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ boolean isTestIdentity = RandomUtils.nextBoolean();
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true);
+
+ String givenName = RandomStringUtils.randomAlphabetic(10);
+ String familyName = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirth = "1956-12-08";
+ String bpk = RandomStringUtils.randomAlphanumeric(10);
+ String cc = pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class);
+ String spC = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+
+ spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + cc + "+" + spC);
+
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setForeigner(false);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.GIVEN_NAME_NAME, givenName);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, familyName);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.BIRTHDATE_NAME, dateOfBirth);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, bpk);
+
+ //set LoA level attribute instead of explicit session-data
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME,
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel());
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setQaaLevel(null);
+
+
+
+ // execute test
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+
+ // validate state
+ Assert.assertNotNull("AuthData null", authData);
+ Assert.assertNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class));
+ Assert.assertNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+
+ Assert.assertEquals("LoA", pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, String.class),
+ authData.getEidasQaaLevel());
+ Assert.assertEquals("CitizenCountry", cc, authData.getCiticenCountryCode());
+ Assert.assertEquals("familyName", familyName, authData.getFamilyName());
+ Assert.assertEquals("givenName", givenName, authData.getGivenName());
+ Assert.assertEquals("DateOfBirth", dateOfBirth, authData.getDateOfBirth());
+
+ Assert.assertEquals("bPK", pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class),
+ authData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class));
+
+ Assert.assertEquals("testIdentity flag",
+ isTestIdentity ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY,
+ ((EidAuthenticationData)authData).getEidStatus());
+ assertFalse("mandate flag", ((EidAuthenticationData)authData).isUseMandate());
+
+ }
+
+ @Test
+ public void eidasProxyModeWithJurMandate() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ injectRepresentativeInfosIntoSession();
+
+ String commonMandate = RandomStringUtils.randomAlphabetic(10);
+
+ // set constant country-code and sourcePin to check hashed eIDAS identifier
+ String sourcePinMandate = "asfdsadfsadfsafsdafsadfasr";
+ spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EE");
+
+ // set nat. person mandate information
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, commonMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME,
+ EaafConstants.URN_PREFIX_BASEID + "+XFN");
+
+ // execute test
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+
+ // validate state
+ Assert.assertNotNull("AuthData null", authData);
+ assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate());
+
+ //check mandate informations
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, commonMandate);
+ checkGenericAttribute(authData, MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ "AT/EE/urn:publicid:gv.at:baseid+XFN+asfdsadfsadfsafsdafsadfasr");
+
+ }
+
+ @Test
+ public void eidasProxyModeWithJurMandateMissingAttribute() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ injectRepresentativeInfosIntoSession();
+
+ // set constant country-code and sourcePin to check hashed eIDAS identifier
+ String sourcePinMandate = "asfdsadfsadfsafsdafsadfasr";
+ spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EE");
+
+ // set nat. person mandate information
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME,
+ EaafConstants.URN_PREFIX_BASEID + "+XFN");
+
+ // execute test
+ // execute test
+ EaafAuthenticationException error = assertThrows(EaafAuthenticationException.class,
+ () -> authenticationDataBuilder.buildAuthenticationData(pendingReq));
+ Assert.assertEquals("wrong errorId", "builder.11", error.getErrorId());
+
+ }
+
+ @Test
+ public void eidasProxyModeWithNatMandate() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ injectRepresentativeInfosIntoSession();
+
+ String givenNameMandate = RandomStringUtils.randomAlphabetic(10);
+ String familyNameMandate = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirthMandate = "1957-09-15";
+ String bpkMandate = RandomStringUtils.randomAlphanumeric(10);
+
+ // set nat. person mandate information
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, "AT+XX:" + bpkMandate);
+
+ // execute test
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+
+ // validate state
+ Assert.assertNotNull("AuthData null", authData);
+ assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate());
+
+ //check mandate informations
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate);
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate);
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "1957-09-15");
+ checkGenericAttribute(authData, MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, bpkMandate);
+
+ }
+
+ @Test
+ public void eidasProxyModeWithNatMandateWrongBpkFormat() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ injectRepresentativeInfosIntoSession();
+
+ String givenNameMandate = RandomStringUtils.randomAlphabetic(10);
+ String familyNameMandate = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirthMandate = "1957-09-15";
+ String bpkMandate = RandomStringUtils.randomAlphanumeric(10);
+
+ // set nat. person mandate information
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate);
+
+ // execute test
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+
+ // validate state
+ Assert.assertNotNull("AuthData null", authData);
+ assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate());
+
+ //check mandate informations
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate);
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate);
+ checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "1957-09-15");
+ checkGenericAttribute(authData, MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, bpkMandate);
+
+ }
+
+ @Test
+ public void eidasProxyModeWithNatMandateMissingAttribute() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ injectRepresentativeInfosIntoSession();
+
+ String familyNameMandate = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirthMandate = "1957-09-15";
+ String bpkMandate = RandomStringUtils.randomAlphanumeric(10);
+
+ // set nat. person mandate information
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate);
+
+ // execute test
+ EaafAuthenticationException error = assertThrows(EaafAuthenticationException.class,
+ () -> authenticationDataBuilder.buildAuthenticationData(pendingReq));
+ Assert.assertEquals("wrong errorId", "builder.11", error.getErrorId());
+
+ }
+
+ @Test
+ public void eidMode() throws EaafAuthenticationException, EaafStorageException {
+ // initialize state
+ boolean isTestIdentity = RandomUtils.nextBoolean();
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, authBlock);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, eidasBind);
+
+ // execute
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+ // validate state
+ Assert.assertNotNull("AuthData null", authData);
+ Assert.assertNotNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class));
+ Assert.assertNotNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+ Assert.assertNotNull("LoA null", authData.getEidasQaaLevel());
+ Assert.assertEquals("testIdentity flag",
+ isTestIdentity ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY,
+ ((EidAuthenticationData)authData).getEidStatus());
+
+ String authBlock = authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ String eidasBind = authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class);
+
+ Assert.assertEquals("authBlock not equal", this.authBlock, authBlock);
+ Assert.assertEquals("eidasBind not equal", this.eidasBind, eidasBind);
+ Assert.assertEquals("piiTransactionId",
+ authData.getGenericData(ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, String.class),
+ this.pendingReq.getUniquePiiTransactionIdentifier());
+ Assert.assertNotNull("assertion validTo", authData.getSsoSessionValidTo());
+ Assert.assertEquals("LoA", pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel(),
+ authData.getEidasQaaLevel());
+ Assert.assertEquals("EID-ISSUING-NATION",
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession(
+ PvpAttributeDefinitions.EID_ISSUING_NATION_NAME),
+ authData.getCiticenCountryCode());
+
+ Assert.assertNull("bPK", authData.getBpk());
+ Assert.assertNull("bPKType", authData.getBpkType());
+ Assert.assertNull("FamilyName", authData.getFamilyName());
+ Assert.assertNull("GivenName", authData.getGivenName());
+ Assert.assertNull("DateOfBirth", authData.getDateOfBirth());
+ Assert.assertNull("baseId", authData.getIdentificationValue());
+ Assert.assertNull("baseIdType", authData.getIdentificationType());
+ Assert.assertNull("IDL", authData.getIdentityLink());
+
+ }
+
+ @Test
+ public void moaIdMode() throws EaafAuthenticationException, EaafBuilderException {
+ //initialize state
+ boolean isTestIdentity = RandomUtils.nextBoolean();
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(false);
+ IIdentityLink idl = buildDummyIdl();
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setIdentityLink(idl);
+
+ //execute
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+ //validate state
+ Assert.assertNotNull("AuthData null", authData);
+ Assert.assertNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class));
+ Assert.assertNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+ Assert.assertNull("piiTransactionId",
+ authData.getGenericData(ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, String.class));
+
+ Assert.assertEquals("testIdentity flag",
+ isTestIdentity ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY,
+ ((EidAuthenticationData)authData).getEidStatus());
+
+ Assert.assertNotNull("assertion validTo", authData.getSsoSessionValidTo());
+ Assert.assertNotNull("LoA null", authData.getEidasQaaLevel());
+ Assert.assertEquals("LoA", pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel(),
+ authData.getEidasQaaLevel());
+ Assert.assertEquals("EID-ISSUING-NATION",
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession(
+ PvpAttributeDefinitions.EID_ISSUING_NATION_NAME),
+ authData.getCiticenCountryCode());
+
+ Assert.assertEquals("FamilyName", idl.getFamilyName(), authData.getFamilyName());
+ Assert.assertEquals("GivenName", idl.getGivenName(), authData.getGivenName());
+ Assert.assertEquals("DateOfBirth", idl.getDateOfBirth(), authData.getDateOfBirth());
+ Assert.assertEquals("bPK",
+ BpkBuilder.generateAreaSpecificPersonIdentifier(
+ idl.getIdentificationValue(), EaafConstants.URN_PREFIX_CDID + "XX").getFirst(),
+ authData.getBpk());
+ Assert.assertEquals("bPKType", EaafConstants.URN_PREFIX_CDID + "XX", authData.getBpkType());
+ Assert.assertNotNull("IDL", authData.getIdentityLink());
+
+
+ }
+
+ private void injectRepresentativeInfosIntoSession() throws EaafStorageException {
+ boolean isTestIdentity = RandomUtils.nextBoolean();
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true);
+
+ String givenName = RandomStringUtils.randomAlphabetic(10);
+ String familyName = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirth = "1956-12-08";
+ String bpk = RandomStringUtils.randomAlphanumeric(10);
+ String cc = pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class);
+ String spC = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + cc + "+" + spC);
+
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setForeigner(false);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.GIVEN_NAME_NAME, givenName);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, familyName);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.BIRTHDATE_NAME, dateOfBirth);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, bpk);
+
+ //set LoA level attribute instead of explicit session-data
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME,
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel());
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setQaaLevel(null);
+
+ }
+
+ private void checkGenericAttribute(IAuthData authData, String attrName, String expected) {
+ assertEquals("Wrong: " + attrName, expected, authData.getGenericData(attrName, String.class));
+
+ }
+
+ private IIdentityLink buildDummyIdl() {
+ return new IIdentityLink() {
+
+ String familyName = RandomStringUtils.randomAlphabetic(10);
+ String givenName = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirth = "1955-02-03";
+ String baseId = RandomStringUtils.randomAlphanumeric(20);
+ String saml2Serialized = RandomStringUtils.randomAlphanumeric(150);
+
+
+
+ @Override
+ public void setSamlAssertion(Element arg0) throws TransformerException, IOException {
+
+ }
+
+ @Override
+ public void setPublicKey(PublicKey[] arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setPrPerson(Element arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIssueInstant(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIdentificationValue(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIdentificationType(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setGivenName(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setFamilyName(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setDsigReferenceTransforms(Element[] arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setDateOfBirth(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getSerializedSamlAssertion() {
+ return this.saml2Serialized;
+ }
+
+ @Override
+ public Element getSamlAssertion() {
+ IIdentityLink fullIdl;
+ try {
+ fullIdl = new SimpleIdentityLinkAssertionParser(
+ AuthenticationDataBuilderTest.class.getResourceAsStream("/data/test_idl_1.xml")).parseIdentityLink();
+ return fullIdl.getSamlAssertion();
+
+ } catch (EaafParserException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public PublicKey[] getPublicKey() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Element getPrPerson() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Date getIssueInstantDate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIssueInstant() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIdentificationValue() {
+ return this.baseId;
+ }
+
+ @Override
+ public String getIdentificationType() {
+ return EaafConstants.URN_PREFIX_BASEID;
+ }
+
+ @Override
+ public String getGivenName() {
+ return this.givenName;
+ }
+
+ @Override
+ public String getFamilyName() {
+ return this.familyName;
+ }
+
+ @Override
+ public Element[] getDsigReferenceTransforms() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getDateOfBirth() {
+ return this.dateOfBirth;
+
+ }
+ };
+ }
+
+}
diff --git a/modules/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties b/modules/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties
new file mode 100644
index 00000000..991036fe
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties
@@ -0,0 +1,113 @@
+## embbeded Tomcat
+tomcat.workingdir=./target/work
+tomcat.ajp.enabled=true
+tomcat.ajp.port=8009
+tomcat.ajp.networkAddress=127.0.0.1
+tomcat.ajp.additionalAttributes.secretrequired=true
+tomcat.ajp.additionalAttributes.secret=junit
+
+## Basic service configuration
+eidas.ms.context.url.prefix=http://localhost
+eidas.ms.core.configRootDir=file:./src/test/resources/config/
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=http://localhost:40900/mockup
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://eidas.node/junit
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+
+#tech. AuthBlock signing for E-ID process
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=keys/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.type=jks
+eidas.ms.pvp2.keystore.path=keys/junit.jks
+eidas.ms.pvp2.keystore.password=password
+eidas.ms.pvp2.key.metadata.alias=meta
+eidas.ms.pvp2.key.metadata.password=password
+eidas.ms.pvp2.key.signing.alias=sig
+eidas.ms.pvp2.key.signing.password=password
+eidas.ms.pvp2.metadata.validity=24
+
+eidas.ms.pvp2.metadata.organisation.name=JUnit
+eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit
+eidas.ms.pvp2.metadata.organisation.url=http://junit.test
+eidas.ms.pvp2.metadata.contact.givenname=Max
+eidas.ms.pvp2.metadata.contact.surname=Mustermann
+eidas.ms.pvp2.metadata.contact.email=max@junit.test
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata
+eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks
+eidas.ms.sp.0.pvp2.metadata.truststore.password=password
+eidas.ms.sp.0.friendlyName=jUnit test
+eidas.ms.sp.0.newEidMode=true
+
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+## Service Provider configuration
+eidas.ms.sp.1.uniqueID=https://demo.egiz.gv.at/junit_test
+eidas.ms.sp.1.pvp2.metadata.truststore=keys/junit.jks
+eidas.ms.sp.1.pvp2.metadata.truststore.password=password
+eidas.ms.sp.1.friendlyName=jUnit test
+eidas.ms.sp.1.pvp2.metadata.url=http://junit.test/metadata
+eidas.ms.sp.1.policy.allowed.requested.targets=test
+eidas.ms.sp.1.policy.hasBaseIdTransferRestriction=true
+
+
+
+#### eIDAS ms-specific Proxy-Service configuration
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
+
diff --git a/modules/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties b/modules/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties
new file mode 100644
index 00000000..de887fe6
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties
@@ -0,0 +1,113 @@
+## embbeded Tomcat
+tomcat.workingdir=./target/work
+tomcat.ajp.enabled=true
+tomcat.ajp.port=8009
+tomcat.ajp.networkAddress=127.0.0.1
+tomcat.ajp.additionalAttributes.secretrequired=true
+tomcat.ajp.additionalAttributes.secret=junit
+
+## Basic service configuration
+eidas.ms.context.url.prefix=http://localhost
+eidas.ms.core.configRootDir=file:./src/test/resources/config/
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://eidas.node/junit
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+
+#tech. AuthBlock signing for E-ID process
+eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s
+eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.keystore.path=keys/teststore.jks
+eidas.ms.auth.eIDAS.authblock.keystore.type=jks
+eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair
+eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false
+
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.type=jks
+eidas.ms.pvp2.keystore.path=keys/junit.jks
+eidas.ms.pvp2.keystore.password=password
+eidas.ms.pvp2.key.metadata.alias=meta
+eidas.ms.pvp2.key.metadata.password=password
+eidas.ms.pvp2.key.signing.alias=sig
+eidas.ms.pvp2.key.signing.password=password
+eidas.ms.pvp2.metadata.validity=24
+
+eidas.ms.pvp2.metadata.organisation.name=JUnit
+eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit
+eidas.ms.pvp2.metadata.organisation.url=http://junit.test
+eidas.ms.pvp2.metadata.contact.givenname=Max
+eidas.ms.pvp2.metadata.contact.surname=Mustermann
+eidas.ms.pvp2.metadata.contact.email=max@junit.test
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata
+eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks
+eidas.ms.sp.0.pvp2.metadata.truststore.password=password
+eidas.ms.sp.0.friendlyName=jUnit test
+eidas.ms.sp.0.newEidMode=true
+
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+## Service Provider configuration
+eidas.ms.sp.1.uniqueID=https://demo.egiz.gv.at/junit_test
+eidas.ms.sp.1.pvp2.metadata.truststore=keys/junit.jks
+eidas.ms.sp.1.pvp2.metadata.truststore.password=password
+eidas.ms.sp.1.friendlyName=jUnit test
+eidas.ms.sp.1.pvp2.metadata.url=http://junit.test/metadata
+eidas.ms.sp.1.policy.allowed.requested.targets=test
+eidas.ms.sp.1.policy.hasBaseIdTransferRestriction=true
+
+
+
+#### eIDAS ms-specific Proxy-Service configuration
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
diff --git a/modules/core_common_webapp/src/test/resources/config/junit_config_3.properties b/modules/core_common_webapp/src/test/resources/config/junit_config_3.properties
new file mode 100644
index 00000000..b4de5aa9
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/config/junit_config_3.properties
@@ -0,0 +1,148 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=
+eidas.ms.context.url.request.validation=false
+eidas.ms.core.configRootDir=file:./src/test/resources/config/
+
+eidas.ms.context.use.clustermode=true
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+eidas.ms.webcontent.templates.countryselection=countrySelection.html
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=
+eidas.ms.auth.eIDAS.node_v2.forward.method=POST
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/substantial
+
+eidas.ms.auth.eIDAS.szrclient.useTestService=true
+eidas.ms.auth.eIDAS.szrclient.endpoint.prod=
+eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks
+eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path=
+eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## PVP2 S-Profile end-point configuration
+eidas.ms.pvp2.keystore.type=jks
+eidas.ms.pvp2.keystore.path=keys/junit.jks
+eidas.ms.pvp2.keystore.password=password
+eidas.ms.pvp2.key.metadata.alias=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.password=
+eidas.ms.pvp2.metadata.validity=24
+
+eidas.ms.pvp2.metadata.organisation.name=JUnit
+eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit
+eidas.ms.pvp2.metadata.organisation.url=http://junit.test
+eidas.ms.pvp2.metadata.contact.givenname=Max
+eidas.ms.pvp2.metadata.contact.surname=Mustermann
+eidas.ms.pvp2.metadata.contact.email=max@junit.test
+
+## Service Provider configuration
+eidas.ms.sp.0.uniqueID=
+eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks
+eidas.ms.sp.0.pvp2.metadata.truststore.password=password
+eidas.ms.sp.0.newEidMode=true
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+
+#### eIDAS ms-specific Proxy-Service configuration
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories= \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/config/log4j.properties b/modules/core_common_webapp/src/test/resources/config/log4j.properties
new file mode 100644
index 00000000..4426ea7e
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/config/log4j.properties
@@ -0,0 +1,54 @@
+# commons-logging setup
+org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory
+
+# define log4j root loggers
+log4j.rootLogger=warn,stdout, console
+
+log4j.logger.at.gv.egiz.eidas.specific=info, msnode
+log4j.logger.at.gv.egiz.eidas.specific.connector.logger.RevisionLogger=info, reversion
+log4j.logger.at.gv.egiz.eidas.specific.connector.logger.StatisticLogger=info, statistic
+log4j.logger.eu.eidas=info, EIDASNODE
+
+log4j.additivity.at.gv.egiz.eidas.specific=false
+log4j.additivity.at.gv.egiz.eidas.specific.connector.logger.RevisionLogger=false
+log4j.additivity.at.gv.egiz.eidas.specific.connector.logger.StatisticLogger=false
+log4j.additivity.eu.eidas=false
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n
+
+log4j.appender.stdout=org.apache.log4j.RollingFileAppender
+log4j.appender.stdout.File=${catalina.base}/logs/console.log
+log4j.appender.stdout.MaxFileSize=10000KB
+log4j.appender.stdout.MaxBackupIndex=9999
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
+
+log4j.appender.msnode=org.apache.log4j.RollingFileAppender
+log4j.appender.msnode.File=${catalina.base}/logs/eidas-ms-reversion.log
+log4j.appender.msnode.MaxFileSize=10000KB
+log4j.appender.msnode.MaxBackupIndex=9999
+log4j.appender.msnode.layout=org.apache.log4j.PatternLayout
+log4j.appender.msnode.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
+
+log4j.appender.reversion=org.apache.log4j.RollingFileAppender
+log4j.appender.reversion.File=${catalina.base}/logs/eidas-ms-reversion.log
+log4j.appender.reversion.MaxFileSize=10000KB
+log4j.appender.reversion.MaxBackupIndex=9999
+log4j.appender.reversion.layout=org.apache.log4j.PatternLayout
+log4j.appender.reversion.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
+
+log4j.appender.statistic=org.apache.log4j.RollingFileAppender
+log4j.appender.statistic.File=${catalina.base}/logs/eidas-ms-statistic.log
+log4j.appender.statistic.MaxFileSize=10000KB
+log4j.appender.statistic.MaxBackupIndex=9999
+log4j.appender.statistic.layout=org.apache.log4j.PatternLayout
+log4j.appender.statistic.layout.ConversionPattern=%m%n
+
+log4j.appender.EIDASNODE=org.apache.log4j.RollingFileAppender
+log4j.appender.EIDASNODE.File=${catalina.base}/logs/eIDAS_node.log
+log4j.appender.EIDASNODE.MaxFileSize=10000KB
+log4j.appender.EIDASNODE.MaxBackupIndex=9999
+log4j.appender.EIDASNODE.layout=org.apache.log4j.PatternLayout
+log4j.appender.EIDASNODE.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/data/metadata_valid.xml b/modules/core_common_webapp/src/test/resources/data/metadata_valid.xml
new file mode 100644
index 00000000..06e1e785
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/data/metadata_valid.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b67c160c0ad7b4ebd430581df167ac23" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata">
+ <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="#_b67c160c0ad7b4ebd430581df167ac23">
+ <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>00SaL0XjeknOb/DttutP50lTyAux1jaRPJIVdSupWvU=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>PfEBmLMX/ZgL6ViXghyWtal5MaMoW8k3zjw+54+WK1OAtVsVgOsIDRJE0M/a/VXBbMSifgY6J1gN23xhr61jkrjRQEkbDzLpWZLzWAJ65YqqUQo8wsKI2Gz0j12yY5D8/GOamKOH9KDi5ba1veXR/fnxRINoy7nZo4tcUWZChdl8BWkMN5ugr6dORNIQg/Ym3GabQ/hR5z+9FmveAKphdH63MC6qW3EgM9EMvOVkrLBTP92sNMAAJeaawui9tlxi9anVQ0OqwZsgKLvI7fyV4CM/0sd/ELjeReIlWlHk07Nz4eltMq3eOx3q1YurYvhE8XapHiQMehOtCS+Fzh10sw==</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>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN
+MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw
+HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN
+MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw
+WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC
+LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG
+SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh
+ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:KeyDescriptor use="encryption">
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/>
+ <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/>
+ <md:AttributeConsumingService index="0" isDefault="true">
+ <md:ServiceName xml:lang="en">Default Service</md:ServiceName>
+ <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
+ <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/>
+ </md:AttributeConsumingService>
+ </md:SPSSODescriptor>
+ <md:Organization>
+ <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName>
+ <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName>
+ <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL>
+ </md:Organization>
+ <md:ContactPerson contactType="technical">
+ <md:Company>E-Government Innovationszentrum</md:Company>
+ <md:GivenName>Lenz</md:GivenName>
+ <md:SurName>Thomas</md:SurName>
+ <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress>
+ <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber>
+ </md:ContactPerson>
+</md:EntityDescriptor>
diff --git a/modules/core_common_webapp/src/test/resources/data/test_idl_1.xml b/modules/core_common_webapp/src/test/resources/data/test_idl_1.xml
new file mode 100644
index 00000000..8151468b
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/data/test_idl_1.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID1467616845518699" IssueInstant="2016-07-04T09:20:45+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0">
+ <saml:AttributeStatement>
+ <saml:Subject>
+ <saml:SubjectConfirmation>
+ <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod>
+ <saml:SubjectConfirmationData>
+ <pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>AT/CZ/xWE0vFWarzpzSL4LYlpst9b6vg0=</pr:Value><pr:Type>urn:publicid:gv.at:eidasid+AT+CZ</pr:Type></pr:Identification><pr:Name><pr:GivenName>XXXMaria-Theresia Kunigunda</pr:GivenName><pr:FamilyName primary="undefined">XXXHabsburg-Lothringen</pr:FamilyName></pr:Name><pr:DateOfBirth>1980-02-29</pr:DateOfBirth></pr:Person>
+ </saml:SubjectConfirmationData>
+ </saml:SubjectConfirmation>
+ </saml:Subject>
+ <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><ecdsa:ECDSAKeyValue><ecdsa:DomainParameters><ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.7"/></ecdsa:DomainParameters><ecdsa:PublicKey><ecdsa:X Value="49629022697474602497707473238246914610217535689798527313620157109614355242988" si:type="ecdsa:PrimeFieldElemType"/><ecdsa:Y Value="77111560713755914450736041751615112402310649832147731609221710465065501356492" si:type="ecdsa:PrimeFieldElemType"/></ecdsa:PublicKey></ecdsa:ECDSAKeyValue></saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><dsig:RSAKeyValue><dsig:Modulus>1BFOitiQUc1lAHDGksneXWZGKGaFBcu03HEiIFsjHjNt/IfRZ4IzqHotUKItxnCdNtsFc1MkMJg+
+g0AXHsuU6MNgcbcXPaPfmHp+8+BJh+amDF3FnAN4ceG8oFAGVEZteOgfdWk1r5RQ2SK+0PuXPuLp
+Tee7IzXtksReZkVEadUCxn/hiRXZa0dABgkFe3kSXbDr5tKXOF0FCtLKhZBI9z+NbX+aTSKOmAOq
+4jyymoo5EP3L+iPecrUwHijD0Bm89h1JjxP521fkYe3Si+0J40okrmCCQHBr+IzB1uX98pKhvs7X
+6rPjOJ6lBwP7XjK7D128P/cg4eH6v58cCfbLcQ==</dsig:Modulus><dsig:Exponent>AQAB</dsig:Exponent></dsig:RSAKeyValue></saml:AttributeValue></saml:Attribute></saml:AttributeStatement>
+
+<dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><dsig:Reference Id="reference-1-1" URI=""><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><dsig:DigestValue>E+BXH0C2F6EYHjdJrOUKr+DsKT8=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue>Hvj40m9ridp2HOz81MTAqzf0q+sZC5YeKpJP43eK5G1HNH1/DNGU/r/6IVPibU9Y
+YGYJoXpznxRFibEQ6dFCHAaNPyADmdGHyJSWryI5ypAap4Y8MJnaUGSWY49IZbht
+PjfKWB2jUNzj1T2u6ebIifAThAK8ZqIE+e5uaR+qrrLicxIhXcSZoyScbKxMuT1Q
+p6zNsNBOHujbVAfKFUE8WmGInyvuoDgerUrA0XstWWg2M9ghytcDJwZpTYwXvmmo
+GV47ue0ITrtM+QqWVbt+dHO8369JFnGQ9h/6h/4j9iyNuxfG7u/EyHQiSuy0+FP8
+1lkLsg1YX+2pN0HElyXVqw==</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIEqzCCBBSgAwIBAgIHANux81oNezANBgkqhkiG9w0BAQUFADBAMSIwIAYDVQQD
+ExlJQUlLIFRlc3QgSW50ZXJtZWRpYXRlIENBMQ0wCwYDVQQKEwRJQUlLMQswCQYD
+VQQGEwJBVDAeFw0xMzA5MjcwNTMzMzdaFw0yMzA5MjcwNTMzMzdaMIHkMQswCQYD
+VQQGEwJBVDENMAsGA1UEBxMER3JhejEmMCQGA1UEChMdR3JheiBVbml2ZXJzaXR5
+IG9mIFRlY2hub2xvZ3kxSDBGBgNVBAsTP0luc3RpdHV0ZSBmb3IgQXBwbGllZCBJ
+bmZvcm1hdGlvbiBQcm9jZXNzaW5nIGFuZCBDb21tdW5pY2F0aW9uczEUMBIGA1UE
+BBMLTU9BLVNTIFRlc3QxGDAWBgNVBCoTD0VHSVogVGVzdHBvcnRhbDEkMCIGA1UE
+AxMbRUdJWiBUZXN0cG9ydGFsIE1PQS1TUyBUZXN0MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAuDjOyf+mY+oQL2FQzzuaiC8C23vVKbq/n2Zi7BqSibZH
+mtqMJfmj4pT+hWSNHvVvWsaxFcx4KeNqdCMzwnw1r4P3Sf+2o5uFku5KHEMLMokR
+yYQG9VqY/KkB94ye7Pv6zT8gvKqxGFg96UamECep4swPaSZrA8AOER5WAtyGDzKI
+Tz+a5zfFaTXDoba7f98PCWR96yKiFjVOhzp38WVz4VJgz+b8ZSY7Xsv5Kn7DXjOL
+STX4MevFLki3rFPup3+4vGToaMBW3PEj67HXBdqR855Le6+E6rVxORqsXqlVwhsI
+6nuS0CO2LWYmBNR1IB0mXteeYH/HfxvuZc+7yDjdPQIDAQABo4IBhDCCAYAwDgYD
+VR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEmcH6VY4BG1EAGB
+TLoNR9vH/g6yMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9jcmxzL0lBSUtUZXN0X0ludGVybWVkaWF0ZUNBLmNybDCBqgYI
+KwYBBQUHAQEEgZ0wgZowSgYIKwYBBQUHMAGGPmh0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9PQ1NQP2NhPUlBSUtUZXN0X0ludGVybWVkaWF0ZUNBMEwGCCsG
+AQUFBzAChkBodHRwOi8vY2EuaWFpay50dWdyYXouYXQvY2Fwc28vY2VydHMvSUFJ
+S1Rlc3RfSW50ZXJtZWRpYXRlQ0EuY2VyMCEGA1UdEQQaMBiBFnRob21hcy5sZW56
+QGVnaXouZ3YuYXQwHwYDVR0jBBgwFoAUaKJeEdreL4BrRES/jfplNoEkp28wDQYJ
+KoZIhvcNAQEFBQADgYEAlFGjUxXLs7SAT8NtXSrv2WrjlklaRnHTFHLQwyVo8JWb
+gvRkHHDUv2o8ofXUY2R2WJ38dxeDoccgbXrJb/Qhi8IY7YhCwv/TuIZDisyAqo8W
+ORKSip/6HWlGCSR/Vgoet1GtCmF0FoUxFUIGSAuQ2yyt4fIzt5GJrU1X5ujjI1w=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo></dsig:Signature></saml:Assertion> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml b/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml
new file mode 100644
index 00000000..bf2c78ac
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <context:annotation-config />
+
+ <import resource="classpath:/SpringTest-context_authManager.xml" />
+
+ <bean id="BasicMSSpecificNodeConfig"
+ class="at.asitplus.eidas.specific.core.config.BasicConfigurationProvider">
+ <constructor-arg
+ value="#{systemProperties['eidas.ms.configuration']}" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml b/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml
new file mode 100644
index 00000000..5a37b98f
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <context:annotation-config />
+
+ <import resource="classpath:/SpringTest-context_authManager.xml" />
+
+ <bean id="basicConfig"
+ class="at.asitplus.eidas.specific.core.config.SpringBootBasicConfigurationProvider" />
+
+ <bean id="eidasNodeMetadata"
+ class="at.asitplus.eidas.specific.core.health.EidasNodeMetadataHealthIndicator" />
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml b/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml
new file mode 100644
index 00000000..966d317a
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml
@@ -0,0 +1,15 @@
+<?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="SimpleInMemoryTransactionStorage"
+ class="at.asitplus.eidas.specific.core.storage.SimpleInMemoryTransactionStorage" />
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml b/modules/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml
new file mode 100644
index 00000000..e66ac987
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml
@@ -0,0 +1,70 @@
+<?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"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ 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
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+ <context:annotation-config />
+ <mvc:annotation-driven />
+ <mvc:default-servlet-handler />
+
+ <bean id="WebResourceConfiguration"
+ class="at.asitplus.eidas.specific.core.config.StaticResourceConfiguration" />
+
+ <bean id="AuthenticationManager"
+ class="at.asitplus.eidas.specific.core.auth.AuthenticationManager" />
+
+ <bean id="AuthenticationDataBuilder"
+ class="at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder" />
+
+ <bean id="eaafProtocolAuthenticationService"
+ class="at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService">
+ <property name="guiBuilder" ref="mvcGUIBuilderImpl" />
+ </bean>
+
+ <bean id="securePendingRequestIdGeneration"
+ class="at.gv.egiz.eaaf.core.impl.utils.SecurePendingRequestIdGenerationStrategy" />
+
+ <bean id="LoALevelMapper"
+ class="at.asitplus.eidas.specific.core.mapper.LoALevelMapper" />
+
+ <bean id="GUIBuilderConfigurationFactory"
+ class="at.asitplus.eidas.specific.core.gui.GuiBuilderConfigurationFactory" />
+
+ <bean id="velocityGUIBuilderImpl"
+ class="at.asitplus.eidas.specific.core.gui.DefaultVelocityGuiBuilderImpl" />
+
+ <bean id="mvcGUIBuilderImpl"
+ class="at.gv.egiz.eaaf.core.impl.gui.builder.SpringMvcGuiFormBuilderImpl" />
+
+ <bean id="templateEngine"
+ class="org.thymeleaf.spring5.SpringTemplateEngine">
+ <property name="templateResolver" ref="templateResolver" />
+ </bean>
+
+ <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
+ <property name="order" value="2" />
+ <property name="templateEngine" ref="templateEngine" />
+ <property name="characterEncoding" value="UTF-8" />
+ </bean>
+
+ <bean id="StatusMessageProvider"
+ class="at.asitplus.eidas.specific.core.provider.StatusMessageProvider" />
+
+ <bean id="eidasRevisionLogger"
+ class="at.asitplus.eidas.specific.core.logger.RevisionLogger" />
+
+ <bean id="eidasStatisticLogger"
+ class="at.asitplus.eidas.specific.core.logger.StatisticLogger" />
+
+ <bean id="defaultErrorHandler"
+ class="at.gv.egiz.eaaf.core.impl.idp.auth.services.DefaultErrorService"/>
+
+</beans> \ No newline at end of file
diff --git a/modules/core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml b/modules/core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml
new file mode 100644
index 00000000..2da610f0
--- /dev/null
+++ b/modules/core_common_webapp/src/test/resources/spring/SpringTest_core_config.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"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ 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
+ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+ <beans profile="deprecatedConfig">
+ <bean id="BasicMSSpecificNodeConfig"
+ class="at.asitplus.eidas.specific.core.config.BasicConfigurationProvider">
+ <constructor-arg value="#{systemProperties['eidas.ms.configuration']}" />
+ </bean>
+ </beans>
+ <beans profile="!deprecatedConfig">
+ <bean id="springBootMsSpecificNodeConfig"
+ class="at.asitplus.eidas.specific.core.config.SpringBootBasicConfigurationProvider" />
+ </beans>
+
+</beans> \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml b/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..cdc9fa95
--- /dev/null
+++ b/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+ <Match>
+ <!-- CSRF protection is implicit available by request token from eIDAS Node and tokens only be logged on trace level -->
+ <Class name="at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController" />
+ <Method name="receiveEidasAuthnRequest" />
+ <OR>
+ <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" />
+ <Bug pattern="CRLF_INJECTION_LOGS" />
+ </OR>
+ </Match>
+ <Match>
+ <!-- Redirect-URL is set by configuration only. Therefore it's trusted -->
+ <Class name="at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServiceAuthenticationAction" />
+ <Method name="forwardToEidasProxy" />
+ <OR>
+ <Bug pattern="UNVALIDATED_REDIRECT" />
+ </OR>
+ </Match>
+</FindBugsFilter>
diff --git a/modules/eidas_proxy-sevice/pom.xml b/modules/eidas_proxy-sevice/pom.xml
new file mode 100644
index 00000000..55a6974c
--- /dev/null
+++ b/modules/eidas_proxy-sevice/pom.xml
@@ -0,0 +1,184 @@
+<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>eidas_proxy-sevice</artifactId>
+ <name>eIDAS specific proxy-service</name>
+ <description>Austrian specific eIDAS Proxy-Service to handle eIDAS Proxy-Service requests from other member states</description>
+
+ <repositories>
+ <repository>
+ <id>eIDASNode-local</id>
+ <name>local</name>
+ <url>file:${basedir}/../../repository</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz.components</groupId>
+ <artifactId>egiz-spring-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>authmodule-eIDAS-v2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_sp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-light-commons</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-specific-communication-definition</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-jcache-ignite-specific-communication</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</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>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>2.0.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>2.0.7</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>authmodule-eIDAS-v2</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </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>
+
+ </dependencies>
+
+<build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs-maven-plugin</artifactId>
+ <version>${spotbugs-maven-plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>post-unit-check</id>
+ <phase>test</phase>
+ <goals>
+ <goal>check</goal>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <haltOnFailure>true</haltOnFailure>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- enable co-existence of testng and junit -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <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/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java
new file mode 100644
index 00000000..23390da8
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java
@@ -0,0 +1,22 @@
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+/**
+ * i18n Message-Source for eIDAS Proxy-Service messages.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasProxyMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/eidasproxy_messages");
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
new file mode 100644
index 00000000..f6a88aa3
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
@@ -0,0 +1,54 @@
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+
+/**
+ * Constants for MS-specific eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+public class MsProxyServiceConstants {
+
+ // general constants
+ public static final String TEMPLATE_SP_UNIQUE_ID = "eidasProxyAuth_from_{0}_type_{1}";
+
+ // configuration constants
+ public static final String CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID = Constants.CONIG_PROPS_EIDAS_NODE
+ + ".proxy.entityId";
+ public static final String CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL = Constants.CONIG_PROPS_EIDAS_NODE
+ + ".proxy.forward.endpoint";
+
+ // mandate configuration
+ public static final String CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.mandates.enabled";
+ public static final String CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.mandates.profiles.natural.default";
+ public static final String CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.mandates.profiles.legal.default";
+
+
+ public static final String CONIG_PROPS_EIDAS_PROXY_WORKAROUND_MANDATES_LEGAL_PERSON =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.workaround.mandates.legalperson";
+
+ // specific eIDAS-Connector configuration
+ public static final String CONIG_PROPS_CONNECTOR_PREFIX = "connector";
+ public static final String CONIG_PROPS_CONNECTOR_UNIQUEID = EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER;
+ public static final String CONIG_PROPS_CONNECTOR_COUNTRYCODE = "countryCode";
+ public static final String CONIG_PROPS_CONNECTOR_MANDATES_ENABLED = "mandates.enabled";
+ public static final String CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL = "mandates.natural";
+ public static final String CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL = "mandates.legal";
+ public static final String CONIG_PROPS_CONNECTOR_VALIDATION_ATTR_MDS = "validation.attributes.mds";
+
+
+ //http end-points
+ public static final String EIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/light/idp/post";
+ public static final String EIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/light/idp/redirect";
+
+ private MsProxyServiceConstants() {
+ //private constructor for class with only constant values
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java
new file mode 100644
index 00000000..d36e4712
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java
@@ -0,0 +1,52 @@
+/*
+ * 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.asitplus.eidas.specific.modules.msproxyservice;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+public class MsProxyServiceSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "MS-specific eIDAS Proxy-Service module";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ return null;
+
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource eidasProxyServiceConfig =
+ new ClassPathResource("/spring/eidas_proxy-service.beans.xml", MsProxyServiceSpringResourceProvider.class);
+
+ return new Resource[] { eidasProxyServiceConfig };
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java
new file mode 100644
index 00000000..43592a28
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java
@@ -0,0 +1,19 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.exception;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+public class EidasProxyServiceException extends EaafException {
+
+ private static final long serialVersionUID = 1L;
+
+ public EidasProxyServiceException(String errorId, Object[] params) {
+ super(errorId, params);
+
+ }
+
+ public EidasProxyServiceException(String errorId, Object[] params, Throwable e) {
+ super(errorId, params, e);
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java
new file mode 100644
index 00000000..e24c753e
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java
@@ -0,0 +1,443 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants;
+import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException;
+import at.asitplus.eidas.specific.modules.msproxyservice.utils.EidasProxyServiceUtils;
+import at.gv.egiz.components.eventlog.api.EventConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes;
+import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import eu.eidas.auth.commons.EIDASSubStatusCode;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.impl.LightResponse;
+import eu.eidas.auth.commons.light.impl.LightResponse.Builder;
+import eu.eidas.auth.commons.light.impl.ResponseStatus;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * End-point implementation for authentication requests from eIDAS Proxy-Service
+ * to MS-specific eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+@Controller
+public class EidasProxyServiceController extends AbstractController implements IModulInfo {
+
+ private static final String ERROR_01 = "eidas.proxyservice.01";
+ private static final String ERROR_02 = "eidas.proxyservice.02";
+ private static final String ERROR_03 = "eidas.proxyservice.03";
+ private static final String ERROR_04 = "eidas.proxyservice.04";
+ private static final String ERROR_05 = "eidas.proxyservice.05";
+ private static final String ERROR_07 = "eidas.proxyservice.07";
+ private static final String ERROR_08 = "eidas.proxyservice.08";
+ private static final String ERROR_09 = "eidas.proxyservice.09";
+ private static final String ERROR_10 = "eidas.proxyservice.10";
+ private static final String ERROR_11 = "eidas.proxyservice.11";
+
+ public static final String PROTOCOL_ID = "eidasProxy";
+
+ @Autowired EidasAttributeRegistry attrRegistry;
+ @Autowired ProxyServiceAuthenticationAction responseAction;
+
+ /**
+ * End-point that receives authentication requests from eIDAS Node.
+ *
+ * @param httpReq Http request
+ * @param httpResp Http response
+ * @throws IOException In case of general error
+ * @throws EaafException In case of a validation or processing error
+ */
+ @RequestMapping(value = {
+ MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_POST,
+ MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_REDIRECT
+ },
+ method = { RequestMethod.POST, RequestMethod.GET })
+ public void receiveEidasAuthnRequest(HttpServletRequest httpReq, HttpServletResponse httpResp)
+ throws IOException,
+ EaafException {
+ log.trace("Receive request on eidas proxy-service end-points");
+ ProxyServicePendingRequest pendingReq = null;
+ try {
+ // get token from Request
+ final String tokenBase64 = httpReq.getParameter(EidasParameterKeys.TOKEN.toString());
+ if (StringUtils.isEmpty(tokenBase64)) {
+ log.warn("NO eIDAS message token found.");
+ throw new EidasProxyServiceException(ERROR_02, null);
+
+ }
+ log.trace("Receive eIDAS-node token: {}. Searching authentication request from eIDAS Proxy-Service ...",
+ tokenBase64);
+
+ // read authentication request from shared cache
+ final SpecificCommunicationService specificProxyCommunicationService =
+ (SpecificCommunicationService) applicationContext.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+ final ILightRequest eidasRequest = specificProxyCommunicationService.getAndRemoveRequest(
+ tokenBase64,
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+ if (eidasRequest == null) {
+ log.info("Find no eIDAS Authn. Request with stated token.");
+ throw new EidasProxyServiceException(ERROR_11, null);
+
+ }
+
+ log.debug("Received eIDAS auth. request from: {}, Initializing authentication environment ... ",
+ eidasRequest.getSpCountryCode() != null ? eidasRequest.getSpCountryCode() : "'missing SP-country'");
+ log.trace("Received eIDAS requst: {}", eidasRequest);
+
+ // create pendingRequest object
+ pendingReq = applicationContext.getBean(ProxyServicePendingRequest.class);
+ pendingReq.initialize(httpReq, authConfig);
+ pendingReq.setModule(getName());
+
+ // log 'transaction created' event
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED,
+ pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(pendingReq.getUniqueSessionIdentifier(),
+ pendingReq.getUniqueTransactionIdentifier(), EventConstants.TRANSACTION_IP,
+ httpReq.getRemoteAddr());
+
+ // validate eIDAS Authn. request and set into pending-request
+ validateEidasAuthnRequest(eidasRequest);
+ pendingReq.setEidasRequest(eidasRequest);
+
+ // generate Service-Provider configuration from eIDAS request
+ final ISpConfiguration spConfig = generateSpConfigurationFromEidasRequest(eidasRequest);
+
+ // validate eIDAS Authn. request by using eIDAS Connector specifc parameters
+ validateEidasAuthnRequest(spConfig, eidasRequest);
+
+ // populate pendingRequest with parameters
+ pendingReq.setOnlineApplicationConfiguration(spConfig);
+ pendingReq.setSpEntityId(spConfig.getUniqueIdentifier());
+ pendingReq.setPassiv(false);
+ pendingReq.setForce(true);
+
+ // AuthnRequest needs authentication
+ pendingReq.setNeedAuthentication(true);
+
+ // set protocol action, which should be executed after authentication
+ pendingReq.setAction(ProxyServiceAuthenticationAction.class.getName());
+
+ // switch to session authentication
+ protAuthService.performAuthentication(httpReq, httpResp, pendingReq);
+
+ } catch (final EidasProxyServiceException e) {
+ throw e;
+
+ } catch (final SpecificCommunicationException e) {
+ log.error("Can not read eIDAS Authn request from shared cache. Reason: {}", e.getMessage());
+ throw new EidasProxyServiceException(ERROR_03, new Object[] { e.getMessage() }, e);
+
+ } catch (final Throwable e) {
+ // write revision log entries
+ if (pendingReq != null) {
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+ pendingReq.getUniqueTransactionIdentifier());
+ }
+
+ throw new EidasProxyServiceException(ERROR_01, new Object[] { e.getMessage() }, e);
+ }
+
+ }
+
+ @Override
+ public boolean generateErrorMessage(Throwable e, HttpServletRequest httpReq, HttpServletResponse httpResp,
+ IRequest pendingReq) throws Throwable {
+ if (pendingReq instanceof ProxyServicePendingRequest) {
+ try {
+ ILightRequest eidasReq = ((ProxyServicePendingRequest) pendingReq).getEidasRequest();
+
+ //build eIDAS response
+ Builder lightRespBuilder = LightResponse.builder();
+ lightRespBuilder.id(UUID.randomUUID().toString());
+ lightRespBuilder.inResponseToId(eidasReq.getId());
+ lightRespBuilder.relayState(eidasReq.getRelayState());
+ lightRespBuilder.issuer(authConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID));
+ lightRespBuilder.subject(UUID.randomUUID().toString());
+ lightRespBuilder.subjectNameIdFormat(NameIDType.TRANSIENT);
+ lightRespBuilder.status(ResponseStatus.builder()
+ .statusCode(StatusCode.RESPONDER)
+ .subStatusCode(EIDASSubStatusCode.AUTHN_FAILED_URI.getValue())
+ .statusMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()))
+ .build());
+
+ // forward to eIDAS Proxy-Service
+ responseAction.forwardToEidasProxy(pendingReq, httpReq, httpResp, lightRespBuilder.build());
+
+ return true;
+
+ } catch (ServletException | IOException | GuiBuildException e1) {
+ log.warn("Forward error to eIDAS Proxy-Service FAILED. Handle error localy ... ", e1);
+
+ }
+
+ } else {
+ log.error("eIDAS Proxy-Service authentication requires PendingRequest of Type: {}",
+ ProxyServicePendingRequest.class.getName());
+
+ }
+
+ return false;
+
+ }
+
+ @Override
+ public String getName() {
+ return EidasProxyServiceController.class.getName();
+
+ }
+
+ @Override
+ public String getAuthProtocolIdentifier() {
+ return PROTOCOL_ID;
+
+ }
+
+ @Override
+ public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) {
+ return true;
+
+ }
+
+ /**
+ * Generic validation of incoming eIDAS request.
+ *
+ * @param eidasRequest Incoming eIDAS authentication request
+ * @throws EidasProxyServiceException In case of a validation error
+ */
+ private void validateEidasAuthnRequest(ILightRequest eidasRequest) throws EidasProxyServiceException {
+ if (StringUtils.isEmpty(eidasRequest.getIssuer())) {
+ throw new EidasProxyServiceException(ERROR_05, null);
+
+ }
+
+ // TODO: validate some other stuff
+
+ }
+
+ /**
+ * eIDAS Connector specific validation of incoming eIDAS request.
+ *
+ * @param eidasRequest Incoming eIDAS authentication request
+ * @param spConfig eIDAS Connector configuration
+ * @throws EidasProxyServiceException In case of a validation error
+ */
+ private void validateEidasAuthnRequest(ISpConfiguration spConfig, ILightRequest eidasRequest)
+ throws EidasProxyServiceException {
+ // check if natural-person and legal-person attributes requested in parallel
+ if (spConfig.isConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_VALIDATION_ATTR_MDS, true)
+ && EidasProxyServiceUtils.isLegalPersonRequested(eidasRequest)
+ && EidasProxyServiceUtils.isNaturalPersonRequested(eidasRequest)) {
+ throw new EidasProxyServiceException(ERROR_08, null);
+
+ }
+
+ // TODO: validate some other stuff
+
+ }
+
+ /**
+ * Generate a dummy Service-Provider configuration for processing.
+ *
+ * @param eidasRequest Incoming eIDAS authentication request
+ * @return Service-Provider configuration that can be used for authentication
+ * @throws EidasProxyServiceException In case of a configuration error
+ */
+ private ISpConfiguration generateSpConfigurationFromEidasRequest(ILightRequest eidasRequest)
+ throws EidasProxyServiceException {
+ try {
+
+ Map<String, String> connectorConfigMap = extractRawConnectorConfiguration(eidasRequest);
+
+ // check if country-code is available
+ String spCountry = connectorConfigMap.get(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE);
+ if (StringUtils.isEmpty(spCountry)) {
+ throw new EidasProxyServiceException(ERROR_07, null);
+
+ }
+
+ // build FriendyName from CountryCode and SPType
+ connectorConfigMap.put(MsEidasNodeConstants.PROP_CONFIG_SP_FRIENDLYNAME,
+ MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID,
+ spCountry, eidasRequest.getSpType()));
+
+ // build Service-Provider configuration object
+ final ServiceProviderConfiguration spConfig = new ServiceProviderConfiguration(connectorConfigMap, authConfig);
+
+ // build bPK target from Country-Code
+ final String ccCountry = authConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE,
+ Constants.DEFAULT_MS_NODE_COUNTRY_CODE);
+ spConfig.setBpkTargetIdentifier(
+ EaafConstants.URN_PREFIX_EIDAS + ccCountry + "+" + spCountry);
+
+ // set required LoA from eIDAS request
+ spConfig.setRequiredLoA(
+ eidasRequest.getLevelsOfAssurance().stream().map(el -> el.getValue()).collect(Collectors.toList()));
+
+ //build mandate profiles for this specific request
+ buildMandateProfileConfiguration(spConfig, eidasRequest);
+
+ return spConfig;
+
+ } catch (EidasProxyServiceException e) {
+ throw e;
+
+ } catch (final EaafException e) {
+ throw new EidasProxyServiceException(ERROR_04, new Object[] { e.getMessage() }, e);
+
+ }
+ }
+
+
+ private Map<String, String> extractRawConnectorConfiguration(ILightRequest eidasRequest) {
+ Map<String, String> allConnectorConfigs = authConfig.getBasicConfigurationWithPrefix(
+ MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_PREFIX);
+ if (log.isTraceEnabled()) {
+ log.trace("Full-connector configuration:");
+ allConnectorConfigs.entrySet().stream().forEach(
+ el -> log.trace("Key: {} -> Value: {}", el.getKey(), el.getValue()));
+
+ }
+
+
+ Map<String, String> connectorConfig = allConnectorConfigs.entrySet().stream()
+ .filter(el -> el.getKey().endsWith(MsEidasNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER)
+ && el.getValue().equals(eidasRequest.getIssuer()))
+ .findFirst()
+ .map(el -> KeyValueUtils.getSubSetWithPrefix(allConnectorConfigs,
+ KeyValueUtils.getParentKey(el.getKey()) + KeyValueUtils.KEY_DELIMITER))
+ .orElse(new HashMap<>());
+
+
+ if (connectorConfig.isEmpty()) {
+ log.debug("No specific configuration for eIDAS Connector: {} Using default configuration ... ",
+ eidasRequest.getIssuer());
+
+ // set EntityId of the requesting eIDAS Connector
+ connectorConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, eidasRequest.getIssuer());
+
+ // set country-code from eIDAS request
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE,
+ eidasRequest.getSpCountryCode());
+
+ // set default mandate configuration
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED,
+ String.valueOf(authConfig.getBasicConfigurationBoolean(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, false)));
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ authConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL));
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ authConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL));
+
+ } else {
+ log.debug("Find specific configuration for eIDAS Connector: {}", eidasRequest.getIssuer());
+
+ }
+
+ return connectorConfig;
+
+ }
+
+
+ private void buildMandateProfileConfiguration(ServiceProviderConfiguration spConfig, ILightRequest eidasRequest)
+ throws EidasProxyServiceException {
+ // check if mandates are enabled
+ if (spConfig.isConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, false)) {
+ injectMandateInfosIntoSpConfig(spConfig, eidasRequest);
+
+ } else {
+ if (EidasProxyServiceUtils.isLegalPersonRequested(eidasRequest)) {
+ throw new EidasProxyServiceException(ERROR_09, null);
+
+ }
+
+ spConfig.setMandateProfiles(Collections.emptyList());
+ spConfig.setMandateMode(SpMandateModes.NONE);
+
+ }
+
+ }
+
+ private void injectMandateInfosIntoSpConfig(ServiceProviderConfiguration spConfig,
+ ILightRequest eidasRequest) throws EidasProxyServiceException {
+ log.trace("eIDAS Proxy-Service allows mandates for Connector: {}. Selecting profiles ... ",
+ spConfig.getUniqueIdentifier());
+
+ //check if legal person is requested
+ if (EidasProxyServiceUtils.isLegalPersonRequested(eidasRequest)) {
+ spConfig.setMandateProfiles(KeyValueUtils.getListOfCsvValues(
+ spConfig.getConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL)));
+ spConfig.setMandateMode(SpMandateModes.LEGAL_FORCE);
+
+ if (spConfig.getMandateProfiles().isEmpty()) {
+ throw new EidasProxyServiceException(ERROR_10, null);
+
+ }
+
+ } else if (EidasProxyServiceUtils.isNaturalPersonRequested(eidasRequest)) {
+ spConfig.setMandateProfiles(KeyValueUtils.getListOfCsvValues(
+ spConfig.getConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL)));
+
+ spConfig.setMandateMode(SpMandateModes.NATURAL);
+
+ }
+
+
+ if (spConfig.getMandateProfiles().isEmpty()) {
+ log.debug("No mandate-profiles for issure: {}. Set mandate-mode to 'none'",
+ spConfig.getUniqueIdentifier());
+ spConfig.setMandateMode(SpMandateModes.NONE);
+
+ } else {
+ log.debug("Set mandate-profiles: {} to request from issuer: {}",
+ spConfig.getMandateProfiles(), spConfig.getUniqueIdentifier());
+
+ }
+
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java
new file mode 100644
index 00000000..15524005
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java
@@ -0,0 +1,374 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.gui.StaticGuiBuilderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants;
+import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException;
+import at.asitplus.eidas.specific.modules.msproxyservice.utils.EidasProxyServiceUtils;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder;
+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.IEidAuthData;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
+import at.gv.egiz.eaaf.core.impl.data.SloInformationImpl;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.light.impl.LightResponse;
+import eu.eidas.auth.commons.light.impl.LightResponse.Builder;
+import eu.eidas.auth.commons.light.impl.ResponseStatus;
+import eu.eidas.auth.commons.tx.BinaryLightToken;
+import eu.eidas.specificcommunication.BinaryLightTokenHelper;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Result action of a successfully performed eIDAS Proxy-Service authentication.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class ProxyServiceAuthenticationAction implements IAction {
+
+ private static final String PROXYSERVICE_AUTH_ACTION_NAME = "MS-specific eIDAS-Proxy action";
+
+ @Autowired
+ ApplicationContext context;
+ @Autowired
+ IConfiguration basicConfig;
+ @Autowired
+ ResourceLoader resourceLoader;
+ @Autowired
+ ISpringMvcGuiFormBuilder guiBuilder;
+ @Autowired
+ EidasAttributeRegistry attrRegistry;
+
+ @Override
+ public SloInformationInterface processRequest(IRequest pendingReq, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, IAuthData authData) throws EaafException {
+ if (pendingReq instanceof ProxyServicePendingRequest) {
+ try {
+ ILightRequest eidasReq = ((ProxyServicePendingRequest) pendingReq).getEidasRequest();
+
+ //build eIDAS response
+ Builder lightRespBuilder = LightResponse.builder();
+ lightRespBuilder.id(UUID.randomUUID().toString());
+ lightRespBuilder.inResponseToId(eidasReq.getId());
+ lightRespBuilder.relayState(eidasReq.getRelayState());
+
+ lightRespBuilder.status(ResponseStatus.builder()
+ .statusCode(Constants.SUCCESS_URI)
+ .build());
+
+ //TODO: check if we can use transient subjectNameIds
+ lightRespBuilder.subject(UUID.randomUUID().toString());
+ lightRespBuilder.subjectNameIdFormat(NameIDType.TRANSIENT);
+
+ //TODO:
+ lightRespBuilder.issuer(basicConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID));
+ lightRespBuilder.levelOfAssurance(authData.getEidasQaaLevel());
+ lightRespBuilder.attributes(buildAttributesFromAuthData(authData, eidasReq));
+
+ // set SLO response object of EAAF framework
+ final SloInformationImpl sloInformation = new SloInformationImpl();
+ sloInformation.setProtocolType(pendingReq.requestedModule());
+ sloInformation
+ .setSpEntityID(pendingReq.getServiceProviderConfiguration().getUniqueIdentifier());
+
+ // forward to eIDAS Proxy-Service
+ forwardToEidasProxy(pendingReq, httpReq, httpResp, lightRespBuilder.build());
+
+ return sloInformation;
+
+ } catch (ServletException | IOException | GuiBuildException e) {
+ throw new EidasProxyServiceException("eidas.proxyservice.06", null, e);
+
+ }
+
+ } else {
+ log.error("eIDAS Proxy-Service authentication requires PendingRequest of Type: {}",
+ ProxyServicePendingRequest.class.getName());
+ throw new EaafException("eidas.proxyservice.99");
+
+ }
+ }
+
+ @Override
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+ return true;
+
+ }
+
+ @Override
+ public String getDefaultActionName() {
+ return PROXYSERVICE_AUTH_ACTION_NAME;
+
+ }
+
+
+ /**
+ * Forward eIDAS Light response to eIDAS node.
+ *
+ * @param pendingReq Current pending request.
+ * @param httpReq Current HTTP request
+ * @param httpResp Current HTTP response
+ * @param lightResponse eIDAS LightResponse
+ * @throws EaafConfigurationException In case of a configuration error
+ * @throws IOException In case of a general error
+ * @throws GuiBuildException In case of a GUI rendering error, if http POST binding is used
+ * @throws ServletException In case of a general error
+ */
+ public void forwardToEidasProxy(IRequest pendingReq, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, LightResponse lightResponse) throws EaafConfigurationException, IOException,
+ GuiBuildException, ServletException {
+
+ // put request into shared cache
+ final BinaryLightToken token = putResponseInCommunicationCache(lightResponse);
+ final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token);
+
+ // select forward URL regarding the selected environment
+ final String forwardUrl = basicConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL);
+
+ if (StringUtils.isEmpty(forwardUrl)) {
+ log.warn("NO ForwardURL defined in configuration. Can NOT forward to eIDAS node! Process stops");
+ throw new EaafConfigurationException("config.08",
+ new Object[] { MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL });
+
+ }
+ log.debug("ForwardURL: " + forwardUrl + " selected to forward eIDAS request");
+
+ if (basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD,
+ Constants.FORWARD_METHOD_GET).equals(Constants.FORWARD_METHOD_GET)) {
+
+ log.debug("Use http-redirect for eIDAS node forwarding ... ");
+ // send redirect
+ final UriComponentsBuilder redirectUrl = UriComponentsBuilder.fromHttpUrl(forwardUrl);
+ redirectUrl.queryParam(EidasParameterKeys.TOKEN.toString(), tokenBase64);
+ httpResp.sendRedirect(redirectUrl.build().encode().toString());
+
+ } else {
+ log.debug("Use http-post for eIDAS node forwarding ... ");
+ final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration(
+ basicConfig,
+ pendingReq,
+ Constants.TEMPLATE_POST_FORWARD_NAME,
+ null,
+ resourceLoader);
+
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_ENDPOINT, forwardUrl);
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_NAME,
+ EidasParameterKeys.TOKEN.toString());
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_VALUE,
+ tokenBase64);
+
+ guiBuilder.build(httpReq, httpResp, config, "Forward to eIDASNode form");
+
+ }
+ }
+
+ @PostConstruct
+ private void checkConfiguration() {
+ //TODO: validate configuration on start-up
+
+ }
+
+
+ private ImmutableAttributeMap buildAttributesFromAuthData(IAuthData authData,
+ ILightRequest eidasReq) {
+ IEidAuthData eidAuthData = (IEidAuthData) authData;
+ if (eidAuthData.isUseMandate()) {
+ log.debug("Building eIDAS Proxy-Service response with mandate ... ");
+ final ImmutableAttributeMap.Builder attributeMap = ImmutableAttributeMap.builder();
+ injectRepesentativeInformation(attributeMap, eidAuthData);
+ injectMandatorInformation(attributeMap, eidAuthData);
+
+ // work-around that injects nat. person subject to bypass validation on eIDAS Node
+ injectJurPersonWorkaroundIfRequired(attributeMap, eidasReq, authData);
+
+ return attributeMap.build();
+
+ } else {
+ log.debug("Building eIDAS Proxy-Service response without mandates ... ");
+ return buildAttributesWithoutMandate(eidAuthData);
+
+ }
+ }
+
+ private void injectMandatorInformation(
+ ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData) {
+ String natMandatorId = eidAuthData.getGenericData(
+ MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, String.class);
+
+ if (StringUtils.isNotEmpty(natMandatorId)) {
+ log.debug("Injecting natural mandator informations ... ");
+ final AttributeDefinition<?> attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition<?> attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition<?> attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition<?> attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+
+ attributeMap.put(attrDefPersonalId, natMandatorId);
+ attributeMap.put(attrDefFamilyName, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, String.class));
+ attributeMap.put(attrDefGivenName, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, String.class));
+ attributeMap.put(attrDefDateOfBirth, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, String.class));
+
+ } else {
+ log.debug("Injecting legal mandator informations ... ");
+ final AttributeDefinition<?> commonName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALNAME).first();
+ final AttributeDefinition<?> legalPersonId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first();
+
+ attributeMap.put(commonName, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, String.class));
+ attributeMap.put(legalPersonId, eidAuthData.getGenericData(
+ MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, String.class));
+
+ }
+ }
+
+ private void injectRepesentativeInformation(
+ ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData) {
+ final AttributeDefinition<?> attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER).first();
+ final AttributeDefinition<?> attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME).first();
+ final AttributeDefinition<?> attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME).first();
+ final AttributeDefinition<?> attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH).first();
+
+ attributeMap.put(attrDefPersonalId,
+ eidAuthData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class));
+ attributeMap.put(attrDefFamilyName, eidAuthData.getFamilyName());
+ attributeMap.put(attrDefGivenName, eidAuthData.getGivenName());
+
+ //TODO: throw an error in case of SZR Date with month or day = "00"
+ attributeMap.put(attrDefDateOfBirth, eidAuthData.getDateOfBirth());
+
+ }
+
+ /**
+ * Work-around to inject representative information as nat. person subject to bypass eIDAS Node validation.
+ *
+ * <p><b>Injection will only be done if this work-around is enabled by configuration,
+ * the mandator is a legal person, and both legal and natural person subject's is requested.</b></p>
+ *
+ * @param attributeMap Attribute set for eIDAS response
+ * @param eidasReq Incoming eIDAS request
+ * @param authData Authentication data
+ */
+ private void injectJurPersonWorkaroundIfRequired(
+ ImmutableAttributeMap.Builder attributeMap, ILightRequest eidasReq, IAuthData authData) {
+ if (isLegalPersonWorkaroundActive() && isLegalPersonMandateAvailable(authData)
+ && EidasProxyServiceUtils.isNaturalPersonRequested(eidasReq)
+ && EidasProxyServiceUtils.isLegalPersonRequested(eidasReq)) {
+ log.debug("Injecting representative information as nat. person subject to bypass eIDAS Node validation");
+ attributeMap.putAll(buildAttributesWithoutMandate(authData));
+
+ }
+ }
+
+ private ImmutableAttributeMap buildAttributesWithoutMandate(IAuthData eidAuthData) {
+ //TODO: throw an error in case of SZR Date with month or day = "00"
+ return buildAttributesWithoutMandate(
+ eidAuthData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class),
+ eidAuthData.getFamilyName(),
+ eidAuthData.getGivenName(),
+ eidAuthData.getDateOfBirth());
+
+ }
+
+ private ImmutableAttributeMap buildAttributesWithoutMandate(String personalIdentifier, String familyName,
+ String givenName, String dateOfBirth) {
+ final AttributeDefinition<?> attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition<?> attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition<?> attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition<?> attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+
+ final ImmutableAttributeMap.Builder attributeMap =
+ ImmutableAttributeMap.builder()
+ .put(attrDefPersonalId, personalIdentifier)
+ .put(attrDefFamilyName, familyName)
+ .put(attrDefGivenName, givenName)
+ .put(attrDefDateOfBirth, dateOfBirth);
+
+ return attributeMap.build();
+
+ }
+
+ private BinaryLightToken putResponseInCommunicationCache(ILightResponse lightResponse)
+ throws ServletException {
+ final BinaryLightToken binaryLightToken;
+ try {
+ final SpecificCommunicationService springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+
+ binaryLightToken = springManagedSpecificConnectorCommunicationService.putResponse(lightResponse);
+
+ } catch (final SpecificCommunicationException e) {
+ log.error("Unable to process specific request");
+ throw new ServletException(e);
+
+ }
+
+ return binaryLightToken;
+ }
+
+ private boolean isLegalPersonWorkaroundActive() {
+ return basicConfig.getBasicConfigurationBoolean(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_WORKAROUND_MANDATES_LEGAL_PERSON,
+ false);
+
+ }
+
+ private boolean isLegalPersonMandateAvailable(IAuthData authData) {
+ return StringUtils.isNoneEmpty(authData.getGenericData(
+ MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, String.class));
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
new file mode 100644
index 00000000..a3b5007a
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
@@ -0,0 +1,28 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+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 eu.eidas.auth.commons.light.ILightRequest;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Pending-request of an authentication process from eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+@Component("ProxyServicePendingRequest")
+@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
+public class ProxyServicePendingRequest extends RequestImpl {
+
+ private static final long serialVersionUID = 4227378344716277935L;
+
+ @Getter
+ @Setter
+ ILightRequest eidasRequest;
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java
new file mode 100644
index 00000000..4cd7ba6c
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java
@@ -0,0 +1,45 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.utils;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import eu.eidas.auth.commons.light.ILightRequest;
+
+/**
+ * Common utils for eIDAS Proxy-Service implementation.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasProxyServiceUtils {
+
+ /**
+ * Check if legal person subject is requested by eIDAS Connector.
+ *
+ * @param eidasRequest Authentication request from eIDAS Connector.
+ * @return <code>true</code> if <i>LegalPersonIdentifier</i> is requested, otherwise <code>false</code>lse
+ */
+ public static boolean isLegalPersonRequested(ILightRequest eidasRequest) {
+ return eidasRequest.getRequestedAttributes().entrySet().stream()
+ .filter(el -> el.getKey().getFriendlyName().equals(Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER))
+ .findFirst()
+ .isPresent();
+
+ }
+
+ /**
+ * Check if natural person subject is requested by eIDAS Connector.
+ *
+ * @param eidasRequest Authentication request from eIDAS Connector.
+ * @return <code>true</code> if <i>PersonIdentifier</i> is requested, otherwise <code>false</code>lse
+ */
+ public static boolean isNaturalPersonRequested(ILightRequest eidasRequest) {
+ return eidasRequest.getRequestedAttributes().entrySet().stream()
+ .filter(el -> el.getKey().getFriendlyName().equals(Constants.eIDAS_ATTR_PERSONALIDENTIFIER))
+ .findFirst()
+ .isPresent();
+
+ }
+
+ private EidasProxyServiceUtils() {
+ //hide constructor for class with static methods only
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
new file mode 100644
index 00000000..9158d2e6
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -0,0 +1 @@
+at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceSpringResourceProvider \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties b/modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties
new file mode 100644
index 00000000..3f92d58a
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties
@@ -0,0 +1,14 @@
+eidas.proxyservice.01=General error on request-validation from national eIDAS Proxy-Service
+eidas.proxyservice.02=Authentication request contains not communication token.
+eidas.proxyservice.03=General error during eIDAS-Node communication. Reason: {}
+eidas.proxyservice.04=Validation of eIDAS Authn request failed. Reason: {}
+eidas.proxyservice.05=No eIDAS-Connector Issuer in Authn. request. Authentication not possible
+eidas.proxyservice.06=Can not build eIDAS Proxy-Service response. Authentication FAILED.
+eidas.proxyservice.07=Can not determine eIDAS-Connector CountryCode. Authentication not possible
+eidas.proxyservice.08=Validation of eIDAS Authn request failed. Reason: Legal person and natural person can not be requested at once.
+eidas.proxyservice.09=eIDAS authentication not possible, because legal person is requested but mandates are disabled in general
+eidas.proxyservice.10=eIDAS authentication not possible, because legal person is requested but not mandate profiles are defined
+eidas.proxyservice.11=No Authentication request with stated communication token.
+
+
+eidas.proxyservice.99=Internal error during eIDAS Proxy-Service authentication \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml b/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml
new file mode 100644
index 00000000..2055b5a9
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml
@@ -0,0 +1,28 @@
+<?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="ProxyServicePendingRequest"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest"
+ scope="prototype"/>
+
+ <bean id="ProxyServiceAuthenticationAction"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServiceAuthenticationAction"/>
+
+ <bean id="msSpecificProxyController"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController"/>
+
+ <bean id="eidasProxyMessageSource"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.EidasProxyMessageSource"/>
+
+
+</beans> \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java
new file mode 100644
index 00000000..efe572b5
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java
@@ -0,0 +1,50 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test;
+
+import java.util.List;
+
+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;
+
+import at.asitplus.eidas.specific.modules.msproxyservice.EidasProxyMessageSource;
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+public class EidasProxyMessageSourceTest {
+
+ @Autowired
+ private ResourceLoader loader;
+ @Autowired(required = false)
+ private List<IMessageSourceLocation> messageSources;
+
+ @Test
+ public void checkMessageSources() {
+ Assert.assertNotNull("No messageSource", messageSources);
+ Assert.assertFalse("No message source", messageSources.isEmpty());
+
+ boolean found = false;
+
+ for (final IMessageSourceLocation messageSource : messageSources) {
+ found = found ? found : messageSource instanceof EidasProxyMessageSource;
+
+ 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());
+
+ }
+ }
+
+ Assert.assertTrue("Internal messagesource not found", found);
+
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java
new file mode 100644
index 00000000..8c6da366
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java
@@ -0,0 +1,56 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.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.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceSpringResourceProvider;
+import at.gv.egiz.eaaf.core.test.TestConstants;
+
+
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class MsProxyServiceSpringResourceProviderTest {
+
+ @Test
+ public void testSpringConfig() {
+ final MsProxyServiceSpringResourceProvider test =
+ new MsProxyServiceSpringResourceProvider();
+ 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",
+ MsProxyServiceSpringResourceProvider.class.getName(), spiFile);
+
+
+ } catch (final IOException e) {
+ Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found");
+
+ }
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java
new file mode 100644
index 00000000..55958d9e
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java
@@ -0,0 +1,666 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.protocol;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService;
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants;
+import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyProtocolAuthService;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+@EnableWebMvc
+public class EidasProxyServiceControllerTest {
+
+ @Autowired private EidasProxyServiceController controller;
+
+ @Autowired private DummySpecificCommunicationService proxyService;
+ @Autowired private DummyProtocolAuthService authService;
+ @Autowired private EidasAttributeRegistry attrRegistry;
+ @Autowired private ApplicationContext context;
+
+ @Autowired MsConnectorDummyConfigMap config;
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+
+ private SpecificCommunicationService springManagedSpecificConnectorCommunicationService;
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+ httpReq = new MockHttpServletRequest("POST", "http://localhost/ms_connector/eidas/light/idp/redirect");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ proxyService.setiLightRequest(null);
+ proxyService.setError(null);
+
+ config.putConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint",
+ "http://eidas.proxy/endpoint");
+
+ springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+
+ }
+
+ @Test
+ public void generateErrorResponseWrongPendingReq() throws Throwable {
+ Assert.assertFalse("wrong statusCode", controller.generateErrorMessage(
+ new EaafException("1000"),
+ httpReq, httpResp, null));
+
+ }
+
+ @Test
+ public void generateErrorResponse() throws Throwable {
+ ProxyServicePendingRequest pendingReq = new ProxyServicePendingRequest();
+ pendingReq.initialize(httpReq, config);
+
+ LightRequest.Builder eidasRequestBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requesterId(RandomStringUtils.randomAlphanumeric(10))
+ .providerName(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+
+ // execute test
+ Assert.assertTrue("wrong statusCode", controller.generateErrorMessage(
+ new EaafException("1000"),
+ httpReq, httpResp,
+ pendingReq));
+
+ // validate state
+ assertNotNull("not redirct Header", httpResp.getHeader("Location"));
+ assertTrue("wrong redirect URL", httpResp.getHeader("Location").startsWith("http://eidas.proxy/endpoint?token="));
+ String token = httpResp.getHeader("Location").substring("http://eidas.proxy/endpoint?token=".length());
+
+ ILightResponse resp = springManagedSpecificConnectorCommunicationService.getAndRemoveResponse(URLDecoder.decode(token, "UTF-8"),
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ assertNotNull("responseId", resp.getId());
+ assertEquals("inResponseTo", pendingReq.getEidasRequest().getId(), resp.getInResponseToId());
+ assertEquals("relayState", pendingReq.getEidasRequest().getRelayState(), resp.getRelayState());
+
+ assertNotNull("subjectNameId", resp.getSubject());
+ assertEquals("subjectNameIdFormat", NameIDType.TRANSIENT, resp.getSubjectNameIdFormat());
+ assertTrue("not attributes", resp.getAttributes().isEmpty());
+
+ assertEquals("StatusCode", StatusCode.RESPONDER, resp.getStatus().getStatusCode());
+ //assertEquals("SubStatusCode", "", resp.getStatus().getSubStatusCode());
+ //assertEquals("StatusMsg", "", resp.getStatus().getStatusMessage());
+
+ }
+
+ @Test
+ public void missingEidasToken() {
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.02", exception.getErrorId());
+
+ }
+
+ @Test
+ public void wrongEidasTokenWithNullpointerException() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.11", exception.getErrorId());
+
+ }
+
+ @Test
+ public void wrongEidasTokenCacheCommunicationError() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ proxyService.setError(new SpecificCommunicationException(RandomStringUtils.randomAlphanumeric(10)));
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.03", exception.getErrorId());
+ Assert.assertTrue("Wrong exception", (exception.getCause() instanceof SpecificCommunicationException));
+
+ }
+
+ @Test
+ public void missingServiceProviderCountry() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH);
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.07", exception.getErrorId());
+
+ }
+
+ @Test
+ public void requestingLegalAndNaturalPerson() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first())
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first())
+ .build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.08", exception.getErrorId());
+
+ }
+
+ @Test
+ public void requestLegalPersonButNoMandates() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "false");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.09", exception.getErrorId());
+
+ }
+
+ @Test
+ public void validAuthnRequest() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "false");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ Assert.assertNotNull("pendingRequest", authService.getPendingReq());
+ Assert.assertTrue("wrong pendingRequest", authService.getPendingReq() instanceof ProxyServicePendingRequest);
+ ProxyServicePendingRequest pendingReq = (ProxyServicePendingRequest) authService.getPendingReq();
+ Assert.assertNotNull("missing uniqueSpId", pendingReq.getSpEntityId());
+ Assert.assertNotNull("missing eidasReq", pendingReq.getEidasRequest());
+
+ Assert.assertFalse("isPassive", pendingReq.isPassiv());
+ Assert.assertTrue("isPassive", pendingReq.forceAuth());
+ Assert.assertFalse("isPassive", pendingReq.isAuthenticated());
+ Assert.assertFalse("isPassive", pendingReq.isAbortedByUser());
+ Assert.assertTrue("isPassive", pendingReq.isNeedAuthentication());
+
+ Assert.assertNotNull("missing spConfig", pendingReq.getServiceProviderConfiguration());
+ ServiceProviderConfiguration spConfig =
+ pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ Assert.assertNotNull("uniqueId", spConfig.getUniqueIdentifier());
+ Assert.assertEquals("uniqueId wrong pattern",
+ authnReqBuilder.build().getIssuer(),
+ spConfig.getUniqueIdentifier());
+ Assert.assertEquals("friendlyName wrong pattern",
+ MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID, spCountryCode, "public"),
+ spConfig.getFriendlyName());
+
+ Assert.assertEquals("uniqueId not match to pendingReq",
+ pendingReq.getSpEntityId(), spConfig.getUniqueIdentifier());
+ Assert.assertNotNull("bpkTarget", spConfig.getAreaSpecificTargetIdentifier());
+ Assert.assertEquals("wrong bPK Target",
+ EaafConstants.URN_PREFIX_EIDAS + "AT+" + spCountryCode,
+ spConfig.getAreaSpecificTargetIdentifier());
+
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultProfilesNat() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ List<String> mandateProfilesNat =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ List<String> mandateProfilesJur =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(mandateProfilesNat, ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(mandateProfilesJur, ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfilesNat.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfilesNat.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.NATURAL, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultProfilesJur() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ List<String> mandateProfilesNat =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ List<String> mandateProfilesJur =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(mandateProfilesNat, ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(mandateProfilesJur, ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfilesJur.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfilesJur.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.LEGAL_FORCE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultNoJurProfiles() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ List<String> mandateProfilesNat =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(mandateProfilesNat, ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL, "");
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.10", exception.getErrorId());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultNoNatProfiles() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL, "");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL, "");
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestIssueSpecificNoMandates() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ String issuer = RandomStringUtils.randomAlphabetic(10);
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(issuer)
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ // set default mandate configuration
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ // set specific mandate configuration
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_UNIQUEID, issuer);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE, spCountryCode);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, "false");
+
+ List<String> mandateProfiles =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ StringUtils.join(mandateProfiles, ","));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ StringUtils.join(Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestIssueSpecificMandatesNat() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ String issuer = "https://apps.egiz.gv.at/EidasNode//ConnectorMetadata";
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(issuer)
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ // set default mandate configuration
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "false");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ // set specific mandate configuration
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_UNIQUEID, issuer);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE, spCountryCode);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, "true");
+
+ List<String> mandateProfiles =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ StringUtils.join(mandateProfiles, ","));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ StringUtils.join(Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfiles.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfiles.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.NATURAL, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestIssueSpecificMandatesJur() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ String issuer = RandomStringUtils.randomAlphabetic(10);
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(issuer)
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ // set default mandate configuration
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ // set specific mandate configuration
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_UNIQUEID, issuer);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE, spCountryCode);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, "true");
+
+ List<String> mandateProfiles =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ StringUtils.join(mandateProfiles, ","));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ StringUtils.join(Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfiles.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfiles.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.LEGAL_FORCE, spConfig.getMandateMode());
+
+ }
+
+ private void addConnectorConfig(int i, String key, String value) {
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_PREFIX + String.valueOf(i) + "." + key,
+ value);
+
+ }
+
+}
+
+
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java
new file mode 100644
index 00000000..52cc01d4
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java
@@ -0,0 +1,637 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.protocol;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.joda.time.DateTime;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummySpConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServiceAuthenticationAction;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.IEidAuthData;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+public class ProxyServiceAuthenticationActionTest {
+
+ @Autowired private MsConnectorDummyConfigMap basicConfig;
+ @Autowired private ProxyServiceAuthenticationAction action;
+ @Autowired private ApplicationContext context;
+ @Autowired EidasAttributeRegistry attrRegistry;
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private ProxyServicePendingRequest pendingReq;
+ private MsConnectorDummySpConfiguration oaParam;
+ private SpecificCommunicationService springManagedSpecificConnectorCommunicationService;
+
+
+ /**
+ * jUnit test set-up.
+ * @throws EaafException In case of an error
+ */
+ @Before
+ public void setUp() throws URISyntaxException, EaafException {
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint",
+ "http://eidas.proxy/endpoint");
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "false");
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new MsConnectorDummySpConfiguration(spConfig, basicConfig);
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+
+ pendingReq = new ProxyServicePendingRequest();
+ pendingReq.initialize(httpReq, basicConfig);
+ pendingReq.setOnlineApplicationConfiguration(oaParam);
+
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+
+ springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+
+ }
+
+ @Test
+ public void wrongPendingRequestType() {
+ IAuthData authData = generateDummyAuthData();
+ TestRequestImpl internalPendingReq = new TestRequestImpl();
+
+ EaafException exception = assertThrows(EaafException.class,
+ () -> action.processRequest(internalPendingReq, httpReq, httpResp, authData));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.99", exception.getErrorId());
+
+ }
+
+ @Test
+ public void missingForwardUrl() {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false);
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint");
+
+ EaafException exception = assertThrows(EaafException.class,
+ () -> action.processRequest(pendingReq, httpReq, httpResp, authData));
+ Assert.assertEquals("wrong errorCode", "config.08", exception.getErrorId());
+
+ }
+
+ @Test
+ public void responseWithoutMandate() throws EaafException, SpecificCommunicationException {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false);
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 4, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH,
+ authData.getDateOfBirth());
+
+ }
+
+ @Test
+ public void responseWithNatMandate() throws EaafException, SpecificCommunicationException {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME,
+ "1985-11-15");
+
+
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 8, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth());
+
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME));
+
+ }
+
+ @Test
+ public void responseWithJurMandate() throws EaafException, SpecificCommunicationException {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 6, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth());
+
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_LEGALNAME,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME));
+
+ assertNull("find nat. person subject: personalId",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+ assertNull("find nat. person subject: familyName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME));
+ assertNull("find nat. person subject: givenName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME));
+ assertNull("find nat. person subject: dateOfBirth",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH));
+
+ }
+
+ @Test
+ public void responseWithNatMandateWithWorkAround() throws EaafException, SpecificCommunicationException {
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "true");
+
+ //request natural person subject only
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder().put(
+ attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME,
+ "1985-11-15");
+
+
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 8, respAttr.size());
+
+ }
+
+ @Test
+ public void responseWithJurMandateWithWorkAround() throws EaafException, SpecificCommunicationException {
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "true");
+
+ //request natural person subject only
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first())
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first())
+ .build());
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 10, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH, authData.getDateOfBirth());
+
+ }
+
+ @Test
+ public void responseWithJurMandateWithWorkAroundNoNatSubject() throws EaafException, SpecificCommunicationException {
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "true");
+
+ //request natural person subject only
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first())
+ .build());
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 6, respAttr.size());
+ assertNull("find nat. person subject: personalId",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+ assertNull("find nat. person subject: familyName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME));
+ assertNull("find nat. person subject: givenName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME));
+ assertNull("find nat. person subject: dateOfBirth",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH));
+
+ }
+
+ @Test
+ public void checkBasicConstrainsInAction() {
+
+ Assert.assertTrue("Wrong NeedAuthentication", action.needAuthentication(pendingReq, httpReq, httpResp));
+ Assert.assertNotNull("Missing ActionName", action.getDefaultActionName());
+
+ Assert.assertNotNull("missing ActionBean", context.getBean(ProxyServiceAuthenticationAction.class));
+
+ }
+
+ private IAuthData generateDummyAuthData() {
+ return generateDummyAuthData(Collections.emptyMap(), EaafConstants.EIDAS_LOA_LOW,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1940-01-01", false);
+
+ }
+
+ private Object getAttrValue(ImmutableAttributeMap respAttr, String attrName) {
+ final AttributeDefinition<?> attrDef =
+ attrRegistry.getCoreAttributeRegistry().getByFriendlyName(attrName).first();
+ return respAttr.getFirstValue(attrDef);
+
+ }
+
+ private void checkAttrValue(ImmutableAttributeMap respAttr, String attrName, String expected) {
+ Object value = getAttrValue(respAttr, attrName);
+ assertNotNull("not attr value: " + attrName, value);
+
+ if (value instanceof String) {
+ assertEquals("wrong attr. value: " + attrName, expected, value);
+
+ } else if ( value instanceof DateTime) {
+ assertEquals("wrong attr. value: " + attrName, expected, ((DateTime)value).toString("yyyy-MM-dd"));
+
+ }
+ }
+
+ private ImmutableAttributeMap validateBasicEidasResponse(IAuthData authData) throws SpecificCommunicationException {
+ assertNotNull("not redirct Header", httpResp.getHeader("Location"));
+ assertTrue("wrong redirect URL", httpResp.getHeader("Location").startsWith("http://eidas.proxy/endpoint?token="));
+ String token = httpResp.getHeader("Location").substring("http://eidas.proxy/endpoint?token=".length());
+
+ ILightResponse resp = springManagedSpecificConnectorCommunicationService.getAndRemoveResponse(URLDecoder.decode(token),
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ assertNotNull("responseId", resp.getId());
+ assertEquals("inResponseTo", pendingReq.getEidasRequest().getId(), resp.getInResponseToId());
+ assertEquals("relayState", pendingReq.getEidasRequest().getRelayState(), resp.getRelayState());
+ assertEquals("LoA", authData.getEidasQaaLevel(), resp.getLevelOfAssurance());
+
+ assertNotNull("subjectNameId", resp.getSubject());
+ assertEquals("subjectNameIdFormat", NameIDType.TRANSIENT, resp.getSubjectNameIdFormat());
+
+ assertFalse("not attributes", resp.getAttributes().isEmpty());
+ return resp.getAttributes();
+
+ }
+
+ private Builder generateBasicLightRequest() {
+ return LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requesterId(RandomStringUtils.randomAlphanumeric(10))
+ .providerName(RandomStringUtils.randomAlphanumeric(10));
+
+ }
+
+ private IAuthData generateDummyAuthData(Map<String, Object> attrs, String loa, String familyName, String givenName, String dateOfBirth,
+ boolean useMandates) {
+ return new IEidAuthData() {
+
+ @Override
+ public boolean isSsoSession() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isForeigner() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isBaseIdTransferRestrication() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Date getSsoSessionValidTo() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getSessionIndex() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getNameIdFormat() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getNameID() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public IIdentityLink getIdentityLink() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIdentificationValue() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIdentificationType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getGivenName() {
+ return givenName;
+ }
+
+ @Override
+ public <T> T getGenericData(String key, Class<T> clazz) {
+ if (attrs.containsKey(key)) {
+ return (T) attrs.get(key);
+
+ } else {
+ return null;
+ }
+
+ }
+
+ @Override
+ public String getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+ @Override
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ @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 loa;
+
+ }
+
+
+ @Override
+ public String getCiticenCountryCode() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getBpkType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getBpk() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getAuthenticationIssuer() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getAuthenticationIssueInstantString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Date getAuthenticationIssueInstant() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte[] getSignerCertificate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte[] getEidToken() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public EidIdentityStatusLevelValues getEidStatus() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getVdaEndPointUrl() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isUseMandate() {
+ return useMandates;
+
+ }
+
+ @Override
+ public String getDateOfBirthFormated(String pattern) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml b/modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml
new file mode 100644
index 00000000..6510546e
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# Copyright (c) 2017 European Commission
+# 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/page/eupl-text-11-12
+# *
+# 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.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>Dynamic attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/AdditionalAttribute</entry>
+ <entry key="1.FriendlyName">AdditionalAttribute</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">false</entry>
+ <entry key="1.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="1.XmlType.LocalPart">string</entry>
+ <entry key="1.XmlType.NamespacePrefix">xs</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalAdditionalAttribute</entry>
+ <entry key="2.FriendlyName">LegalAdditionalAttribute</entry>
+ <entry key="2.PersonType">LegalPerson</entry>
+ <entry key="2.Required">false</entry>
+ <entry key="2.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="2.XmlType.LocalPart">string</entry>
+ <entry key="2.XmlType.NamespacePrefix">xs</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+</properties>
diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml b/modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml
new file mode 100644
index 00000000..cbae35db
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml
@@ -0,0 +1,376 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# Copyright (c) 2017 European Commission
+# 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/page/eupl-text-11-12
+# *
+# 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.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>eIDAS attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier</entry>
+ <entry key="1.FriendlyName">PersonIdentifier</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">true</entry>
+ <entry key="1.UniqueIdentifier">true</entry>
+ <entry key="1.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="1.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="1.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</entry>
+ <entry key="2.FriendlyName">FamilyName</entry>
+ <entry key="2.PersonType">NaturalPerson</entry>
+ <entry key="2.Required">true</entry>
+ <entry key="2.TransliterationMandatory">true</entry>
+ <entry key="2.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="2.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="2.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="3.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</entry>
+ <entry key="3.FriendlyName">FirstName</entry>
+ <entry key="3.PersonType">NaturalPerson</entry>
+ <entry key="3.Required">true</entry>
+ <entry key="3.TransliterationMandatory">true</entry>
+ <entry key="3.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="3.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="3.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="3.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="4.NameUri">http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</entry>
+ <entry key="4.FriendlyName">DateOfBirth</entry>
+ <entry key="4.PersonType">NaturalPerson</entry>
+ <entry key="4.Required">true</entry>
+ <entry key="4.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="4.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="4.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="4.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="5.NameUri">http://eidas.europa.eu/attributes/naturalperson/BirthName</entry>
+ <entry key="5.FriendlyName">BirthName</entry>
+ <entry key="5.PersonType">NaturalPerson</entry>
+ <entry key="5.Required">false</entry>
+ <entry key="5.TransliterationMandatory">true</entry>
+ <entry key="5.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="5.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="5.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="5.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="6.NameUri">http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth</entry>
+ <entry key="6.FriendlyName">PlaceOfBirth</entry>
+ <entry key="6.PersonType">NaturalPerson</entry>
+ <entry key="6.Required">false</entry>
+ <entry key="6.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="6.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="6.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="6.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="7.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentAddress</entry>
+ <entry key="7.FriendlyName">CurrentAddress</entry>
+ <entry key="7.PersonType">NaturalPerson</entry>
+ <entry key="7.Required">false</entry>
+ <entry key="7.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="7.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="7.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="7.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.CurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="8.NameUri">http://eidas.europa.eu/attributes/naturalperson/Gender</entry>
+ <entry key="8.FriendlyName">Gender</entry>
+ <entry key="8.PersonType">NaturalPerson</entry>
+ <entry key="8.Required">false</entry>
+ <entry key="8.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="8.XmlType.LocalPart">GenderType</entry>
+ <entry key="8.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="8.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="9.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier</entry>
+ <entry key="9.FriendlyName">LegalPersonIdentifier</entry>
+ <entry key="9.PersonType">LegalPerson</entry>
+ <entry key="9.Required">true</entry>
+ <entry key="9.UniqueIdentifier">true</entry>
+ <entry key="9.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="9.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="9.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="9.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="10.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalName</entry>
+ <entry key="10.FriendlyName">LegalName</entry>
+ <entry key="10.PersonType">LegalPerson</entry>
+ <entry key="10.Required">true</entry>
+ <entry key="10.TransliterationMandatory">true</entry>
+ <entry key="10.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="10.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="10.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="10.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="11.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonAddress</entry>
+ <entry key="11.FriendlyName">LegalAddress</entry>
+ <entry key="11.PersonType">LegalPerson</entry>
+ <entry key="11.Required">false</entry>
+ <entry key="11.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="11.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="11.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="11.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.LegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="12.NameUri">http://eidas.europa.eu/attributes/legalperson/VATRegistrationNumber</entry>
+ <entry key="12.FriendlyName">VATRegistration</entry>
+ <entry key="12.PersonType">LegalPerson</entry>
+ <entry key="12.Required">false</entry>
+ <entry key="12.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="12.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="12.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="12.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="13.NameUri">http://eidas.europa.eu/attributes/legalperson/TaxReference</entry>
+ <entry key="13.FriendlyName">TaxReference</entry>
+ <entry key="13.PersonType">LegalPerson</entry>
+ <entry key="13.Required">false</entry>
+ <entry key="13.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="13.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="13.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="13.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="14.NameUri">http://eidas.europa.eu/attributes/legalperson/D-2012-17-EUIdentifier</entry>
+ <entry key="14.FriendlyName">D-2012-17-EUIdentifier</entry>
+ <entry key="14.PersonType">LegalPerson</entry>
+ <entry key="14.Required">false</entry>
+ <entry key="14.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="14.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="14.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="14.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="15.NameUri">http://eidas.europa.eu/attributes/legalperson/LEI</entry>
+ <entry key="15.FriendlyName">LEI</entry>
+ <entry key="15.PersonType">LegalPerson</entry>
+ <entry key="15.Required">false</entry>
+ <entry key="15.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="15.XmlType.LocalPart">LEIType</entry>
+ <entry key="15.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="15.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="16.NameUri">http://eidas.europa.eu/attributes/legalperson/EORI</entry>
+ <entry key="16.FriendlyName">EORI</entry>
+ <entry key="16.PersonType">LegalPerson</entry>
+ <entry key="16.Required">false</entry>
+ <entry key="16.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="16.XmlType.LocalPart">EORIType</entry>
+ <entry key="16.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="16.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="17.NameUri">http://eidas.europa.eu/attributes/legalperson/SEED</entry>
+ <entry key="17.FriendlyName">SEED</entry>
+ <entry key="17.PersonType">LegalPerson</entry>
+ <entry key="17.Required">false</entry>
+ <entry key="17.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="17.XmlType.LocalPart">SEEDType</entry>
+ <entry key="17.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="17.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="18.NameUri">http://eidas.europa.eu/attributes/legalperson/SIC</entry>
+ <entry key="18.FriendlyName">SIC</entry>
+ <entry key="18.PersonType">LegalPerson</entry>
+ <entry key="18.Required">false</entry>
+ <entry key="18.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="18.XmlType.LocalPart">SICType</entry>
+ <entry key="18.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="18.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="19.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PersonIdentifier</entry>
+ <entry key="19.FriendlyName">RepresentativePersonIdentifier</entry>
+ <entry key="19.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="19.Required">false</entry>
+ <entry key="19.UniqueIdentifier">true</entry>
+ <entry key="19.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="19.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="19.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="19.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="20.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentFamilyName</entry>
+ <entry key="20.FriendlyName">RepresentativeFamilyName</entry>
+ <entry key="20.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="20.Required">false</entry>
+ <entry key="20.TransliterationMandatory">true</entry>
+ <entry key="20.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="20.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="20.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="20.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="21.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentGivenName</entry>
+ <entry key="21.FriendlyName">RepresentativeFirstName</entry>
+ <entry key="21.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="21.Required">false</entry>
+ <entry key="21.TransliterationMandatory">true</entry>
+ <entry key="21.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="21.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="21.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="21.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="22.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/DateOfBirth</entry>
+ <entry key="22.FriendlyName">RepresentativeDateOfBirth</entry>
+ <entry key="22.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="22.Required">false</entry>
+ <entry key="22.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="22.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="22.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="22.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="23.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/BirthName</entry>
+ <entry key="23.FriendlyName">RepresentativeBirthName</entry>
+ <entry key="23.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="23.Required">false</entry>
+ <entry key="23.TransliterationMandatory">true</entry>
+ <entry key="23.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="23.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="23.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="23.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="24.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PlaceOfBirth</entry>
+ <entry key="24.FriendlyName">RepresentativePlaceOfBirth</entry>
+ <entry key="24.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="24.Required">false</entry>
+ <entry key="24.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="24.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="24.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="24.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="25.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentAddress</entry>
+ <entry key="25.FriendlyName">RepresentativeCurrentAddress</entry>
+ <entry key="25.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="25.Required">false</entry>
+ <entry key="25.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="25.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="25.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="25.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvCurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="26.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/Gender</entry>
+ <entry key="26.FriendlyName">RepresentativeGender</entry>
+ <entry key="26.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="26.Required">false</entry>
+ <entry key="26.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="26.XmlType.LocalPart">GenderType</entry>
+ <entry key="26.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="26.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="27.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonIdentifier</entry>
+ <entry key="27.FriendlyName">RepresentativeLegalPersonIdentifier</entry>
+ <entry key="27.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="27.Required">false</entry>
+ <entry key="27.UniqueIdentifier">true</entry>
+ <entry key="27.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="27.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="27.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="27.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="28.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalName</entry>
+ <entry key="28.FriendlyName">RepresentativeLegalName</entry>
+ <entry key="28.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="28.Required">false</entry>
+ <entry key="28.TransliterationMandatory">true</entry>
+ <entry key="28.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="28.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="28.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="28.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="29.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="29.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="29.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="29.Required">false</entry>
+ <entry key="29.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="29.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="29.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="29.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="30.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="30.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="30.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="30.Required">false</entry>
+ <entry key="30.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="30.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="30.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="30.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="31.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/TaxReference</entry>
+ <entry key="31.FriendlyName">RepresentativeTaxReference</entry>
+ <entry key="31.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="31.Required">false</entry>
+ <entry key="31.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="31.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="31.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="31.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="32.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/D-2012-17-EUIdentifier</entry>
+ <entry key="32.FriendlyName">RepresentativeD-2012-17-EUIdentifier</entry>
+ <entry key="32.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="32.Required">false</entry>
+ <entry key="32.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="32.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="32.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="32.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="33.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LEI</entry>
+ <entry key="33.FriendlyName">RepresentativeLEI</entry>
+ <entry key="33.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="33.Required">false</entry>
+ <entry key="33.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="33.XmlType.LocalPart">LEIType</entry>
+ <entry key="33.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="33.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="34.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/EORI</entry>
+ <entry key="34.FriendlyName">RepresentativeEORI</entry>
+ <entry key="34.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="34.Required">false</entry>
+ <entry key="34.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="34.XmlType.LocalPart">EORIType</entry>
+ <entry key="34.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="34.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="35.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SEED</entry>
+ <entry key="35.FriendlyName">RepresentativeSEED</entry>
+ <entry key="35.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="35.Required">false</entry>
+ <entry key="35.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="35.XmlType.LocalPart">SEEDType</entry>
+ <entry key="35.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="35.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="36.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SIC</entry>
+ <entry key="36.FriendlyName">RepresentativeSIC</entry>
+ <entry key="36.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="36.Required">false</entry>
+ <entry key="36.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="36.XmlType.LocalPart">SICType</entry>
+ <entry key="36.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="36.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="39.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="39.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="39.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="39.Required">false</entry>
+ <entry key="39.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="39.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="39.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="39.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="40.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="40.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="40.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="40.Required">false</entry>
+ <entry key="40.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="40.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="40.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="40.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+
+</properties>
diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties b/modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties
new file mode 100644
index 00000000..4f3b82b5
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties
@@ -0,0 +1,6 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=http://localhost
+eidas.ms.context.url.request.validation=false
+
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml
new file mode 100644
index 00000000..fe9ff441
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.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">
+
+ <context:annotation-config />
+
+ <bean id="dummyMapBasedConfiguration"
+ class="at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap">
+ <constructor-arg value="/config/junit_config_1.properties" />
+ <property name="configRootDirSufix" value="src/test/resources/config" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml
new file mode 100644
index 00000000..9870d22a
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml
@@ -0,0 +1,42 @@
+<?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:/SpringTest-context_authManager.xml" />
+ <import resource="classpath:/spring/eidas_proxy-service.beans.xml"/>
+
+ <bean id="springManagedSpecificProxyserviceCommunicationService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService" />
+
+ <bean id="mvcGUIBuilderImpl"
+ class="at.gv.egiz.eaaf.core.impl.gui.builder.SpringMvcGuiFormBuilderImpl" />
+
+ <bean id="specificConnectorAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/eidas-attributes.xml" />
+ </bean>
+
+ <bean id="specificConnectorAdditionalAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/additional-attributes.xml" />
+ </bean>
+
+ <bean id="attributeRegistry"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry">
+ <property name="eidasAttributesFile"
+ ref="specificConnectorAttributesFileWithPath" />
+ <property name="additionalAttributesFile"
+ ref="specificConnectorAdditionalAttributesFileWithPath" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/pom.xml b/modules/pom.xml
new file mode 100644
index 00000000..e0b87b3e
--- /dev/null
+++ b/modules/pom.xml
@@ -0,0 +1,23 @@
+<?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.asitplus.eidas</groupId>
+ <artifactId>ms_specific</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <packaging>pom</packaging>
+
+ <name>Modules for MS specific eIDAS Node</name>
+
+ <modules>
+ <module>core_common_lib</module>
+ <module>core_common_webapp</module>
+ <module>authmodule-eIDAS-v2</module>
+ <module>authmodule_id-austria</module>
+ <module>eidas_proxy-sevice</module>
+ </modules>
+
+</project>