From fa2384985454568439dc286a6a9051fba47322ed Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 25 Jan 2021 16:30:07 +0100 Subject: add ID Austria communication-module and additional jUnit test It's first alpha-version of eIDAS MS-specific Proxy-Service with ID Austria authentication --- .../builder/AuthenticationDataBuilder.java | 3 + .../src/main/resources/application.properties | 71 ++- .../test/utils/AuthenticationDataBuilderTest.java | 80 ++- .../resources/config/junit_config_1.properties | 30 + .../config/junit_config_1_springboot.properties | 32 +- .../config/junit_config_2_springboot.properties | 30 + .../resources/config/junit_config_3.properties | 31 + .../src/test/resources/config/keys/junit_test.jks | Bin 0 -> 8410 bytes .../specific/modules/auth/eidas/v2/Constants.java | 3 +- .../eidas/v2/tasks/GenerateAuthnRequestTask.java | 14 +- .../test/tasks/GenerateAuthnRequestTaskTest.java | 4 +- .../checks/spotbugs-exclude.xml | 19 + eidas_modules/authmodule_id-austria/pom.xml | 5 +- .../auth/idaustria/IdAustriaAuthConstants.java | 111 ++++ .../EidasConnecorUniqueIdAttributeBuilder.java | 52 ++ .../config/IdAustriaAuthMessageSource.java | 22 + .../config/IdAustriaAuthMetadataConfiguration.java | 462 ++++++++++++++ .../IdAustriaAuthRequestBuilderConfiguration.java | 307 +++++++++ .../IdAustriaAuthMetadataController.java | 150 +++++ .../controller/IdAustriaAuthSignalController.java | 94 +++ .../tasks/ReceiveFromIdAustriaSystemTask.java | 377 +++++++++++ .../tasks/RequestIdAustriaSystemTask.java | 209 +++++++ .../utils/IdAustriaAuthCredentialProvider.java | 130 ++++ .../utils/IdAustriaAuthMetadataProvider.java | 168 +++++ .../at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder | 1 + .../messages/idaustria_auth_messages.properties | 10 + .../process/id_austria.Authentication.process.xml | 20 +- .../resources/spring/id_austria_auth.beans.xml | 19 + .../resources/spring/id_austria_task.beans.xml | 8 + .../EidasConnecorUniqueIdAttributeBuilderTest.java | 54 ++ .../config/IdAustriaAuthMessageSourceTest.java | 50 ++ .../IdAustriaAuthMetadataControllerFirstTest.java | 183 ++++++ .../IdAustriaAuthSignalControllerTest.java | 200 ++++++ .../test/task/ReceiveAuthnResponseTaskTest.java | 690 +++++++++++++++++++++ .../test/task/RequestIdAustriaSystemTaskTest.java | 380 ++++++++++++ .../utils/IdAustriaAuthCredentialProviderTest.java | 413 ++++++++++++ .../IdAustriaAuthMetadataProviderFirstTest.java | 235 +++++++ .../IdAustriaAuthMetadataProviderSecondTest.java | 65 ++ .../src/test/resources/config/junit.jks | Bin 0 -> 3980 bytes .../resources/config/junit_config_1.properties | 44 ++ .../src/test/resources/config/junit_test.jks | Bin 0 -> 8410 bytes .../resources/config/junit_test_no_trust_certs.jks | Bin 0 -> 4818 bytes .../src/test/resources/config/pvp.jks | Bin 0 -> 4833 bytes .../src/test/resources/config/pvp.p12 | Bin 0 -> 5494 bytes .../src/test/resources/data/Response_with_EID.xml | 49 ++ .../data/Response_with_EID_bpk_without_prefix.xml | 49 ++ .../resources/data/Response_with_EID_minimum.xml | 43 ++ .../Response_with_EID_with_eid_sector_attr.xml | 52 ++ .../data/Response_with_EID_wrong_data.xml | 46 ++ .../Response_with_wrong_destination_endpoint.xml | 52 ++ .../Response_without_sig_classpath_entityid.xml | 52 ++ .../data/Response_without_sig_with_error.xml | 46 ++ ...sponse_without_sig_with_error_empty_subcode.xml | 46 ++ .../Response_without_sig_with_error_userstop.xml | 46 ++ ...onse_without_sig_with_error_without_subcode.xml | 45 ++ .../src/test/resources/data/eidas_node_siging.crt | 21 + .../data/idp_metadata_classpath_entity.xml | 146 +++++ .../test/resources/data/idp_metadata_no_sig.xml | 46 ++ .../test/resources/data/idp_metadata_no_sig2.xml | 46 ++ .../resources/data/idp_metadata_sig_notvalid.xml | 84 +++ .../data/idp_metadata_sig_valid_wrong_alg.xml | 74 +++ .../resources/data/junit_keystore_metadata.crt | 11 + .../test/resources/data/junit_keystore_signing.crt | 18 + .../src/test/resources/data/moa_sig_signing.crt | 27 + .../resources/data/pvp_postbinding_template.html | 3 + .../src/test/resources/data/sp_metadata_junit.xml | 66 ++ .../spring/SpringTest-context_basic_test.xml | 12 +- .../resources/spring/SpringTest-context_lazy.xml | 24 + .../eidas_proxy-sevice/checks/spotbugs-exclude.xml | 8 + .../msproxyservice/MsProxyServiceConstants.java | 12 + .../protocol/EidasProxyServiceController.java | 59 +- .../protocol/ProxyServiceAuthenticationAction.java | 200 +++++- .../messages/eidasproxy_messages.properties | 1 + .../ProxyServiceAuthenticationActionTest.java | 70 ++- .../resources/config/junit_config_1.properties | 5 +- .../spring/SpringTest-context_basic_test.xml | 3 + pom.xml | 15 + 77 files changed, 6157 insertions(+), 96 deletions(-) create mode 100644 connector/src/test/resources/config/keys/junit_test.jks create mode 100644 eidas_modules/authmodule_id-austria/checks/spotbugs-exclude.xml create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/EidasConnecorUniqueIdAttributeBuilder.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMessageSource.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMetadataConfiguration.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthRequestBuilderConfiguration.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthMetadataController.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthSignalController.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthCredentialProvider.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthMetadataProvider.java create mode 100644 eidas_modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder create mode 100644 eidas_modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/EidasConnecorUniqueIdAttributeBuilderTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/config/IdAustriaAuthMessageSourceTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthSignalControllerTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderSecondTest.java create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/config/junit.jks create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test.jks create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.jks create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.p12 create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/pvp_postbinding_template.html create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml create mode 100644 eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java index 3a93c1b8..2e70893b 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java @@ -86,6 +86,9 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder ((EidAuthenticationData)authData).setEidStatus(authProcessData.isTestIdentity() ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY); + + + } else { throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: " + authData.getClass().getName()); diff --git a/connector/src/main/resources/application.properties b/connector/src/main/resources/application.properties index e7437840..f6d9bb7e 100644 --- a/connector/src/main/resources/application.properties +++ b/connector/src/main/resources/application.properties @@ -8,6 +8,7 @@ server.servlet.contextPath=/ms_connector app.build.artifactId=ms_connector + ############################################################################# ## SpringBoot Admin client spring.boot.admin.client.enabled=false @@ -16,9 +17,9 @@ spring.boot.admin.client.enabled=false ## SpringBoot Actuator management.endpoints.web.exposure.include=health,info - ############################################################################# -## MS-speccific eIDAS-Connector configuration +## Common parts of MS-speccific eIDAS application configuration + #eidas.ms.context.url.prefix= eidas.ms.context.url.request.validation=false #eidas.ms.configRootDir=file:/.../config/ @@ -48,6 +49,29 @@ eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256 #eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret +## HTTP-client defaults +eidas.ms.client.http.connection.timeout.socket=15 +eidas.ms.client.http.connection.timeout.connection=15 +eidas.ms.client.http.connection.timeout.request=15 + + +## Common PVP2 S-Profile (SAML2) 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 + +##only for advanced config +eidas.ms.configuration.pvp.scheme.validation=true +eidas.ms.configuration.pvp.enable.entitycategories=false + + + +############################################################################# +## MS-speccific eIDAS-Connector configuration + ## eIDAS Ref. Implementation connector ### eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector eidas.ms.auth.eIDAS.eid.testidentity.default=false @@ -139,13 +163,6 @@ eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true #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 @@ -159,5 +176,37 @@ eidas.ms.pvp2.metadata.validity=24 ##only for advanced config eidas.ms.configuration.sp.disableRegistrationRequirement=false -eidas.ms.configuration.pvp.scheme.validation=true -eidas.ms.configuration.pvp.enable.entitycategories=false \ No newline at end of file + + + +############################################################################# +## MS-speccific eIDAS-Proxy-Service configuration + +#### eIDAS ms-specific Proxy-Service configuration +eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy +#eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint= + + +## PVP2 S-Profile communication with ID Austria System +# EntityId and optional metadata of ID Austria System +#eidas.ms.modules.idaustriaauth.idp.entityId= +#eidas.ms.modules.idaustriaauth.idp.metadataUrl= + +# SAML2 client configuration +eidas.ms.modules.idaustriaauth.keystore.type=jks +#eidas.ms.modules.idaustriaauth.keystore.name= +#eidas.ms.modules.idaustriaauth.keystore.path= +#eidas.ms.modules.idaustriaauth.keystore.password= +#eidas.ms.modules.idaustriaauth.metadata.sign.alias= +#eidas.ms.modules.idaustriaauth.metadata.sign.password= +#eidas.ms.modules.idaustriaauth.request.sign.alias= +#eidas.ms.modules.idaustriaauth.request.sign.password= +#eidas.ms.modules.idaustriaauth.response.encryption.alias= +#eidas.ms.modules.idaustriaauth.response.encryption.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= +#eidas.ms.modules.idaustriaauth.truststore.password= + diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java index 17ecb2ca..552c448e 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java @@ -32,6 +32,7 @@ import org.w3c.dom.Element; import at.asitplus.eidas.specific.connector.builder.AuthenticationDataBuilder; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants; 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; @@ -72,6 +73,7 @@ public class AuthenticationDataBuilderTest { private TestRequestImpl pendingReq; private DummySpConfiguration oaParam; + private Map spConfig; private String eidasBind; private String authBlock; @@ -92,7 +94,7 @@ public class AuthenticationDataBuilderTest { RequestContextHolder.resetRequestAttributes(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); - final Map spConfig = new HashMap<>(); + 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"); @@ -105,26 +107,90 @@ public class AuthenticationDataBuilderTest { pendingReq.setSpConfig(oaParam); authBlock = RandomStringUtils.randomAlphanumeric(20); eidasBind = RandomStringUtils.randomAlphanumeric(20); - pendingReq.getSessionData(AuthProcessDataWrapper.class) - .setGenericDataToSession(Constants.SZR_AUTHBLOCK, authBlock); - pendingReq.getSessionData(AuthProcessDataWrapper.class) - .setGenericDataToSession(Constants.EIDAS_BIND, eidasBind); 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)); + RandomStringUtils.randomAlphabetic(2).toUpperCase()); LocaleContextHolder.resetLocaleContext(); } @Test - public void eidMode() throws EaafAuthenticationException { + 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(MsProxyServiceConstants.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(Constants.SZR_AUTHBLOCK, String.class)); + Assert.assertNull("eidasBind null", authData.getGenericData(Constants.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.getFormatedDateOfBirth()); + + Assert.assertEquals("bPK", pendingReq.getSessionData(AuthProcessDataWrapper.class) + .getGenericDataFromSession(MsProxyServiceConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class), + authData.getGenericData(MsProxyServiceConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class)); + + Assert.assertEquals("testIdentity flag", + isTestIdentity ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY, + ((EidAuthenticationData)authData).getEidStatus()); + + + } + + @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(Constants.SZR_AUTHBLOCK, authBlock); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(Constants.EIDAS_BIND, eidasBind); // execute IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); diff --git a/connector/src/test/resources/config/junit_config_1.properties b/connector/src/test/resources/config/junit_config_1.properties index f6b3e4c1..044e33a6 100644 --- a/connector/src/test/resources/config/junit_config_1.properties +++ b/connector/src/test/resources/config/junit_config_1.properties @@ -116,6 +116,36 @@ 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 + + ##only for advanced config eidas.ms.configuration.sp.disableRegistrationRequirement= #eidas.ms.configuration.restrictions.baseID.spTransmission= diff --git a/connector/src/test/resources/config/junit_config_1_springboot.properties b/connector/src/test/resources/config/junit_config_1_springboot.properties index e63cda7b..991036fe 100644 --- a/connector/src/test/resources/config/junit_config_1_springboot.properties +++ b/connector/src/test/resources/config/junit_config_1_springboot.properties @@ -43,7 +43,6 @@ 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 @@ -81,3 +80,34 @@ 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/connector/src/test/resources/config/junit_config_2_springboot.properties b/connector/src/test/resources/config/junit_config_2_springboot.properties index ecb22dec..de887fe6 100644 --- a/connector/src/test/resources/config/junit_config_2_springboot.properties +++ b/connector/src/test/resources/config/junit_config_2_springboot.properties @@ -81,3 +81,33 @@ 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/connector/src/test/resources/config/junit_config_3.properties b/connector/src/test/resources/config/junit_config_3.properties index 8b2c63a8..b4de5aa9 100644 --- a/connector/src/test/resources/config/junit_config_3.properties +++ b/connector/src/test/resources/config/junit_config_3.properties @@ -109,6 +109,37 @@ eidas.ms.sp.0.newEidMode=true #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= diff --git a/connector/src/test/resources/config/keys/junit_test.jks b/connector/src/test/resources/config/keys/junit_test.jks new file mode 100644 index 00000000..ee6254a9 Binary files /dev/null and b/connector/src/test/resources/config/keys/junit_test.jks differ diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java index c8da9a4e..e2200ed1 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java @@ -48,8 +48,9 @@ public class Constants { 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_NODE_FORWARD_URL = CONIG_PROPS_EIDAS_NODE + 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 = diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java index 9900fa98..d1e69e84 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateAuthnRequestTask.java @@ -143,7 +143,7 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { } // select forward URL regarding the selected environment - String forwardUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL); + String forwardUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL); if (StringUtils.isNotEmpty(environment)) { forwardUrl = selectedForwardUrlForEnvironment(environment); } @@ -151,8 +151,8 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { 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_NODE_FORWARD_URL - : Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL + "." + environment + environment == null ? Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL + : Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL + "." + environment }); } @@ -214,17 +214,17 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { 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_NODE_FORWARD_URL); + 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_NODE_FORWARD_URL + 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_NODE_FORWARD_URL + 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_NODE_FORWARD_URL + return basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL + "." + MsEidasNodeConstants.REQ_PARAM_SELECTED_ENVIRONMENT_VALUE_DEVELOPMENT); } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java index 4edfe32d..624700f9 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateAuthnRequestTaskTest.java @@ -137,7 +137,7 @@ public class GenerateAuthnRequestTaskTest { .getErrorId()); Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException()) .getParams().length); - Assert.assertEquals("wrong errorMsg", Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL, ((EaafException) e + Assert.assertEquals("wrong errorMsg", Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL, ((EaafException) e .getOriginalException()).getParams()[0]); } @@ -162,7 +162,7 @@ public class GenerateAuthnRequestTaskTest { .getErrorId()); Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException()) .getParams().length); - Assert.assertEquals("wrong errorMsg", Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL + "." + stage, ((EaafException) e + Assert.assertEquals("wrong errorMsg", Constants.CONIG_PROPS_EIDAS_CONNECTOR_NODE_FORWARD_URL + "." + stage, ((EaafException) e .getOriginalException()).getParams()[0]); } diff --git a/eidas_modules/authmodule_id-austria/checks/spotbugs-exclude.xml b/eidas_modules/authmodule_id-austria/checks/spotbugs-exclude.xml new file mode 100644 index 00000000..311c3a8e --- /dev/null +++ b/eidas_modules/authmodule_id-austria/checks/spotbugs-exclude.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/eidas_modules/authmodule_id-austria/pom.xml b/eidas_modules/authmodule_id-austria/pom.xml index 25cbfc2e..3aabb069 100644 --- a/eidas_modules/authmodule_id-austria/pom.xml +++ b/eidas_modules/authmodule_id-austria/pom.xml @@ -79,7 +79,6 @@ mockwebserver test - at.asitplus.eidas.ms_specific connector_lib @@ -130,9 +129,9 @@ com.github.spotbugs spotbugs-maven-plugin ${spotbugs-maven-plugin.version} - + diff --git a/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java b/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java new file mode 100644 index 00000000..18eaee4b --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java @@ -0,0 +1,111 @@ +package at.asitplus.eidas.specific.modules.auth.idaustria; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +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"; + + public static final List> DEFAULT_REQUIRED_PVP_ATTRIBUTES = + Collections.unmodifiableList(new ArrayList>() { + 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)); + + } + }); + + public static final List DEFAULT_REQUIRED_PVP_ATTRIBUTE_NAMES = + Collections.unmodifiableList(new ArrayList() { + private static final long serialVersionUID = 1L; + { + for (final Triple el : DEFAULT_REQUIRED_PVP_ATTRIBUTES) { + if (el.getThird()) { + add(el.getFirst()); + + } + } + } + }); +} diff --git a/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/EidasConnecorUniqueIdAttributeBuilder.java b/eidas_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/eidas_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 build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator g) + throws AttributeBuilderException { + return g.buildStringAttribute(EIDAS_CONNECTOR_UNIQUEID_FRIENDLY_NAME, EIDAS_CONNECTOR_UNIQUEID_NAME, + oaParam.getUniqueIdentifier()); + + } + + @Override + public ATT buildEmpty(final IAttributeGenerator g) { + return g.buildEmptyAttribute(EIDAS_CONNECTOR_UNIQUEID_FRIENDLY_NAME, EIDAS_CONNECTOR_UNIQUEID_NAME); + + } + +} diff --git a/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMessageSource.java b/eidas_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/eidas_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 getMessageSourceLocation() { + return Arrays.asList("classpath:messages/idaustria_auth_messages"); + + } + +} diff --git a/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthMetadataConfiguration.java b/eidas_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/eidas_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 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 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 getIdpPossibleAttributes() { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder# + * getIDPPossibleNameITTypes() + */ + @Override + public List getIdpPossibleNameIdTypes() { + return null; + } + + + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder# + * getSPRequiredAttributes() + */ + @Override + public Collection getSpRequiredAttributes() { + final Map 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 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> additionalAttr) { + if (additionalAttr != null && !additionalAttr.isEmpty()) { + additionalAttributes = new ArrayList<>(); + for (final Pair 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 requestedAttributes, + List> attributes) { + for (final Triple el : attributes) { + requestedAttributes.put(el.getFirst(), PvpAttributeBuilder.buildReqAttribute(el.getFirst(), el + .getSecond(), el.getThird())); + + } + } + +} diff --git a/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/config/IdAustriaAuthRequestBuilderConfiguration.java b/eidas_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/eidas_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 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 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 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/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthMetadataController.java b/eidas_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/eidas_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> getAdditonalRequiredAttributes() { + final List> result = new ArrayList<>(); + // load attributes from configuration + final Map 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 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/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/controller/IdAustriaAuthSignalController.java b/eidas_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/eidas_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/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java b/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java new file mode 100644 index 00000000..5dc04800 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java @@ -0,0 +1,377 @@ +package at.asitplus.eidas.specific.modules.auth.idaustria.tasks; + +import java.io.IOException; +import java.util.List; +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.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.msproxyservice.MsProxyServiceConstants; +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 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 = authConfig.getBasicConfiguration( + IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID); + 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 List 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 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()); + + // TODO: add mandates if SEMPER are integrated + + } catch (final EaafException | IOException e) { + throw new EaafBuilderException(ERROR_PVP_06, null, e.getMessage(), e); + + } + } + + 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(MsProxyServiceConstants.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 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().getMessage() }); + + } + + } + + /** + * Get SAML2 Sub-StatusCode if not null. + * + * @param samlResp SAML2 response + * @return Sub-StatusCode or null 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/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java b/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java new file mode 100644 index 00000000..fc46ac8b --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java @@ -0,0 +1,209 @@ +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.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.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.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 = authConfig.getBasicConfiguration( + IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_ENTITYID); + 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 requiredLoA) { + //TODO: implement LoA selection + return requiredLoA.get(0); + + } + + private List buildRequestedAttributes(IRequest pendingReq) { + final List attributs = new ArrayList<>(); + + //build attribute that contains the unique identifier of the eIDAS-Connector + final Attribute attrEidasConnectorId = PvpAttributeBuilder.buildEmptyAttribute( + ExtendedPvpAttributeDefinitions.EIDAS_CONNECTOR_UNIQUEID_NAME); + final EaafRequestedAttribute attrEidasConnectorIdReqAttr = Saml2Utils.generateReqAuthnAttributeSimple( + attrEidasConnectorId, + true, + pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); + attributs.add(attrEidasConnectorIdReqAttr); + + + // build EID sector for identification attribute + final Attribute attr = PvpAttributeBuilder.buildEmptyAttribute( + PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME); + final EaafRequestedAttribute bpkTargetReqAttr = Saml2Utils.generateReqAuthnAttributeSimple( + attr, + true, + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + attributs.add(bpkTargetReqAttr); + + + // set requested LoA as attribute + final Attribute loaAttr = PvpAttributeBuilder.buildEmptyAttribute( + PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME); + final EaafRequestedAttribute loaReqAttr = Saml2Utils.generateReqAuthnAttributeSimple( + loaAttr, + true, + selectHighestLoa(pendingReq.getServiceProviderConfiguration().getRequiredLoA())); + attributs.add(loaReqAttr); + + + //set ProviderName if available + String providerName = ((ProxyServicePendingRequest)pendingReq).getEidasRequest().getProviderName(); + if (StringUtils.isNotEmpty(providerName)) { + final Attribute providerNameAttr = PvpAttributeBuilder.buildEmptyAttribute( + ExtendedPvpAttributeDefinitions.SP_FRIENDLYNAME_NAME); + final EaafRequestedAttribute providerNameReqAttr = Saml2Utils.generateReqAuthnAttributeSimple( + providerNameAttr, + true, + providerName); + attributs.add(providerNameReqAttr); + + } + + + //set ProviderName if available + String requesterId = ((ProxyServicePendingRequest)pendingReq).getEidasRequest().getRequesterId(); + if (StringUtils.isNotEmpty(requesterId)) { + final Attribute requesterIdAttr = PvpAttributeBuilder.buildEmptyAttribute( + ExtendedPvpAttributeDefinitions.SP_UNIQUEID_NAME); + final EaafRequestedAttribute requesterIdReqAttr = Saml2Utils.generateReqAuthnAttributeSimple( + requesterIdAttr, + true, + requesterId); + attributs.add(requesterIdReqAttr); + + } + + return attributs; + } + +} diff --git a/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthCredentialProvider.java b/eidas_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/eidas_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/eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/utils/IdAustriaAuthMetadataProvider.java b/eidas_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/eidas_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 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 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 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/eidas_modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder b/eidas_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/eidas_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/eidas_modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties b/eidas_modules/authmodule_id-austria/src/main/resources/messages/idaustria_auth_messages.properties new file mode 100644 index 00000000..6de6e0dc --- /dev/null +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml b/eidas_modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml index e46b3c15..ebd5c54d 100644 --- a/eidas_modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml +++ b/eidas_modules/authmodule_id-austria/src/main/resources/process/id_austria.Authentication.process.xml @@ -2,19 +2,17 @@ - - - - + + + + + + + + - - - - - - - + diff --git a/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml b/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml index adb54dc8..d2d16bf9 100644 --- a/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml +++ b/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_auth.beans.xml @@ -14,4 +14,23 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml b/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml index f95d71cc..9da9145d 100644 --- a/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml +++ b/eidas_modules/authmodule_id-austria/src/main/resources/spring/id_austria_task.beans.xml @@ -11,5 +11,13 @@ + + + + \ No newline at end of file diff --git a/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/EidasConnecorUniqueIdAttributeBuilderTest.java b/eidas_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/eidas_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. + *
+ * The attribute-value is read from {@link ISpConfiguration} with method getUniqueIdentifier() + * + * @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/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/config/IdAustriaAuthMessageSourceTest.java b/eidas_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/eidas_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 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/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java new file mode 100644 index 00000000..ef0c4da0 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java @@ -0,0 +1,183 @@ +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.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.connector.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 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(7); + + } + + @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(8); + + } + + 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()); + + //check XML scheme + final SchemaValidationFilter schemaFilter = new SchemaValidationFilter(); + schemaFilter.filter(metadata); + + //check signature + final SimpleMetadataSignatureVerificationFilter sigFilter = + new SimpleMetadataSignatureVerificationFilter(credProvider.getKeyStore().getFirst(), + metadata.getEntityID()); + sigFilter.filter(metadata); + + //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).getFormat()); + + Assert.assertFalse("AttributeConsumingServices", + spSsoDesc.getAttributeConsumingServices().isEmpty()); + Assert.assertEquals("#RequestAttributes", numberOfRequestedAttributes, + spSsoDesc.getAttributeConsumingServices().get(0).getRequestAttributes().size()); + + } + + private List convertX509Certs(List certs) { + final List result = new ArrayList<>(); + for (final X509Certificate cert : certs) { + result.add(new BasicX509Credential(cert)); + + } + return result; + } +} diff --git a/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthSignalControllerTest.java b/eidas_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/eidas_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 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/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java new file mode 100644 index 00000000..a0446ad9 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java @@ -0,0 +1,690 @@ +package at.asitplus.eidas.specific.modules.auth.idaustria.test.task; + +import static org.junit.Assert.assertThrows; + +import java.io.IOException; +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.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.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.connector.config.ServiceProviderConfiguration; +import at.asitplus.eidas.specific.connector.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.MsProxyServiceConstants; +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 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()); + + 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,MsProxyServiceConstants.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,MsProxyServiceConstants.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,MsProxyServiceConstants.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,MsProxyServiceConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY="); + + } + + 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(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(idpEntityId); + response.setIssuer(issuer); + + if (validConditions) { + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + } + + return Saml2Utils.signSamlObject(response, credential, true); + } +} diff --git a/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java new file mode 100644 index 00000000..e5493332 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java @@ -0,0 +1,380 @@ +package at.asitplus.eidas.specific.modules.auth.idaustria.test.task; + +import static org.junit.Assert.assertThrows; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +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.connector.config.ServiceProviderConfiguration; +import at.asitplus.eidas.specific.connector.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.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.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 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", 3, 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()); + + } + + @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", 5, 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()); + + } + + 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 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; + + } + }; + } +} diff --git a/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java new file mode 100644 index 00000000..99a00089 --- /dev/null +++ b/eidas_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.connector.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 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 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/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java new file mode 100644 index 00000000..fa0d95a6 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java @@ -0,0 +1,235 @@ +package at.asitplus.eidas.specific.modules.auth.idaustria.test.utils; + +import java.io.IOException; + +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.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.connector.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(DateTime.now().plusDays(1)); + 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/eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderSecondTest.java b/eidas_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/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/config/junit.jks b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit.jks new file mode 100644 index 00000000..59e6ad13 Binary files /dev/null and b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit.jks differ diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties index e69de29b..66c13dbc 100644 --- a/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_config_1.properties +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test.jks b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test.jks new file mode 100644 index 00000000..ee6254a9 Binary files /dev/null and b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test.jks differ diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks new file mode 100644 index 00000000..8fe3b03c Binary files /dev/null and b/eidas_modules/authmodule_id-austria/src/test/resources/config/junit_test_no_trust_certs.jks differ diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.jks b/eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.jks new file mode 100644 index 00000000..f0a5a09a Binary files /dev/null and b/eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.jks differ diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.p12 b/eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.p12 new file mode 100644 index 00000000..183342f7 Binary files /dev/null and b/eidas_modules/authmodule_id-austria/src/test/resources/config/pvp.p12 differ diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml new file mode 100644 index 00000000..8d3c1c66 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID.xml @@ -0,0 +1,49 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/high + + + AT + + + Mustermann + + + Max + + + 1940-01-01 + + + AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_bpk_without_prefix.xml @@ -0,0 +1,49 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/aabbcc + + + AT + + + Heinz + + + Susi + + + 1955-01-01 + + + QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY= + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml new file mode 100644 index 00000000..be8e7cc3 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_minimum.xml @@ -0,0 +1,43 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + AT + + + Mustermann + + + Max + + + 1940-01-01 + + + AT+CC:QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.xml b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_with_eid_sector_attr.xml @@ -0,0 +1,52 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/aabbcc + + + AT + + + Heinz + + + Susi + + + 1955-01-01 + + + AT+AB:QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY= + + + urn:publicid:gv.at:eidasid+AT+AB + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml new file mode 100644 index 00000000..cc534d09 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_EID_wrong_data.xml @@ -0,0 +1,46 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + piiId_112233445566 + + + 2.1 + + + http://eidas.europa.eu/LoA/low + + + IT + + + aabbccddeeffgghh + + + MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA== + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml new file mode 100644 index 00000000..2ae05ca1 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_with_wrong_destination_endpoint.xml @@ -0,0 +1,52 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://www.stork.gov.eu/1.0/citizenQAALevel/4 + + + + + 2.1 + + + Mustermann + + + Max + + + 1940-01-01 + + + BF:QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + 4 + + + AT + + + urn:publicid:gv.at:cdid+BF + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml new file mode 100644 index 00000000..0fd675e2 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_classpath_entityid.xml @@ -0,0 +1,52 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + Mustermann + + + Max + + + 1940-01-01 + + + BF:QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + http://eidas.europa.eu/LoA/high + + + IT + + + urn:publicid:gv.at:cdid+BF + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml new file mode 100644 index 00000000..ee5920dc --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error.xml @@ -0,0 +1,46 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + Der Anmeldevorgang wurde durch den Benutzer abgebrochen. + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/low + + + IT + + + aabbccddeeffgghh + + + MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA== + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_empty_subcode.xml @@ -0,0 +1,46 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + Der Anmeldevorgang wurde durch den Benutzer abgebrochen. + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/low + + + IT + + + aabbccddeeffgghh + + + MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA== + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_userstop.xml @@ -0,0 +1,46 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + + Der Anmeldevorgang wurde durch den Benutzer abgebrochen. + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/low + + + IT + + + aabbccddeeffgghh + + + MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA== + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/Response_without_sig_with_error_without_subcode.xml @@ -0,0 +1,45 @@ + + + classpath:/data/idp_metadata_classpath_entity.xml + + + + Der Anmeldevorgang wurde durch den Benutzer abgebrochen. + + + https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata + + QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + + + + https://localhost/authhandler/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.1 + + + http://eidas.europa.eu/LoA/low + + + IT + + + aabbccddeeffgghh + + + MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDENMAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRhMB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SYO4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYIKoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImnAiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA== + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt b/eidas_modules/authmodule_id-austria/src/test/resources/data/eidas_node_siging.crt new file mode 100644 index 00000000..95843ea9 --- /dev/null +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml new file mode 100644 index 00000000..de565887 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_classpath_entity.xml @@ -0,0 +1,146 @@ + + + + + + + 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== + + + + 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= + + + + MIIBbjCCARSgAwIBAgIEXh7TNzAKBggqhkjOPQQDAjA/MQswCQYDVQQGEwJBVDEN + MAsGA1UECgwERUdJWjEOMAwGA1UECwwFalVuaXQxETAPBgNVBAMMCG1ldGFkYXRh + MB4XDTIwMDExNTA4NTQxNVoXDTMwMDExNDA4NTQxNVowPzELMAkGA1UEBhMCQVQx + DTALBgNVBAoMBEVHSVoxDjAMBgNVBAsMBWpVbml0MREwDwYDVQQDDAhtZXRhZGF0 + YTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBdBkaxt31p++aZeP3SmlWITj9SY + O4McV2ccXFsH4X4QMHuKAMUvjxPm1kdU01eTOWdiQX0GpDIBspYMZh8ZKcwwCgYI + KoZIzj0EAwIDSAAwRQIhAJ3QKlk9cd90s+i8y62fvmGF6LtfNO+JvkWqDUBeQImn + AiA2KwFtzO7STAp9MEwQGe0vt0F8mO1ttrLE+rr6YxdwGA== + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + + + + + + + + + + + + + + + + + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml new file mode 100644 index 00000000..bc55fe62 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig.xml @@ -0,0 +1,46 @@ + + + + + + + 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== + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + + + + + + + + + + + + + + + + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml new file mode 100644 index 00000000..bdc176a0 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_no_sig2.xml @@ -0,0 +1,46 @@ + + + + + + + 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== + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + + + + + + + + + + + + + + + + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml new file mode 100644 index 00000000..86665a9c --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_notvalid.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + e6DiHa9scuvxJFBUipZ8PQcD4kAkmSIDZgZV+0/7glg= + + + Czr2EwhK/0ZUZ5blQpJfNoOFEscLlxlmHPjmOJUIsxlB2pUn+ApULrjVpR1ViUcGZ0PVi2KChSNoSn09YKjtgPFBiSY010VYdaACgqluxUt6AwESObaqcyHVBzMDUr/g6jkRFEJV4vqnZQQDdDfTH4MXNqunORegS1saBHw4nJSOX4YfoVmIuT5uOlRrxvoG7srnGShvF7DmvIHBUBF5Tq9FyeSgwTM8udxl8Yl9FB2pREuR83CcbgjPrYKtzi6TiSfrWkcD0L5BvmMxN/BdaGDAorxYOnk41sWDJjrkY8C2SC1YDy6XT4SM06uFwstUrRn8QPg1hfbLHAyQNoaR8ecgapk5DkxmbATMcGY+SM4yQWkBdYT7GtufNmF8sIVaL6JOOTKAE9qqX/1N6N4zOPmm8rpIqVEQZtQ5usN/ubxbxLxUoTdDeo8RwkktW6zQ3Zv9+Iyf0DASYmK1IxN+fMw/qyeVy9r6o15ITHTqTmT/7BidKZ58m4HxIK52E3DU + + + 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= + + + + + + + + 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== + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + + + + + + + + + + + + + + + + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/idp_metadata_sig_valid_wrong_alg.xml @@ -0,0 +1,74 @@ + + dhkHkgZ1OOHG0nYWiRXrpZhIAx41103CG6DKDbBra8o=AkxnEu9g3QgYC0JwuJXMYFrnNn6UMtrbtVn5YzkKBXxyYqZui4pEi/TRSM9r7Gt+ +4UqHrJVkYMbbuoO2kpiDnluPG+vHYzYFvF0agQ+gfGjpVQNRORN0FU7JPX+KPjpr +sMU8wVZITSPU0GBBccvzrcpq7DQt0VbV5U7/Vq3KM/fop4ytAkUbTltUj/XxvAd1 +XdhB/zyeTTR2dafJ6Z2CKyM7MMmxwXYD1NrPGciPvTJ9ASHAT0lJM1dxrRNbeAja +KTrNVj78MhSluRm5g7N1pMZzgMSpqN66AUg8pkSTvcRaNImPzYDcMQzHl2Tr362M +RudjSgaEljK98TbBdgLFTg==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= + + + + 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== + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt b/eidas_modules/authmodule_id-austria/src/test/resources/data/junit_keystore_metadata.crt new file mode 100644 index 00000000..35831d03 --- /dev/null +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt b/eidas_modules/authmodule_id-austria/src/test/resources/data/junit_keystore_signing.crt new file mode 100644 index 00000000..35a82125 --- /dev/null +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt b/eidas_modules/authmodule_id-austria/src/test/resources/data/moa_sig_signing.crt new file mode 100644 index 00000000..fda99f2b --- /dev/null +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/pvp_postbinding_template.html b/eidas_modules/authmodule_id-austria/src/test/resources/data/pvp_postbinding_template.html new file mode 100644 index 00000000..5c65e25a --- /dev/null +++ b/eidas_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/eidas_modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml b/eidas_modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml new file mode 100644 index 00000000..32e90604 --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/data/sp_metadata_junit.xml @@ -0,0 +1,66 @@ + + + + + + + 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= + + + + + + + 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= + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + + + + Default Service + + + + + + + + + + + + + + + + + diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml b/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml index 0f42ceb5..16959dc5 100644 --- a/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml +++ b/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_test.xml @@ -11,8 +11,18 @@ - + + + + + + + + \ No newline at end of file diff --git a/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml b/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml new file mode 100644 index 00000000..5360960b --- /dev/null +++ b/eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_lazy.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + diff --git a/eidas_modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml b/eidas_modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml index 53ca4d4d..cdc9fa95 100644 --- a/eidas_modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml +++ b/eidas_modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml @@ -9,4 +9,12 @@ + + + + + + + + diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java index a7c3b8e2..e5d4d33e 100644 --- a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java +++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java @@ -1,5 +1,9 @@ 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.PvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder; + /** * Constants for MS-specific eIDAS Proxy-Service. * @@ -11,7 +15,15 @@ public class MsProxyServiceConstants { //general constants public static final String TEMPLATE_SP_UNIQUE_ID = "eidasProxyAuth_from_{0}_type_{1}"; + public static final String ATTR_EIDAS_PERSONAL_IDENTIFIER = + AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER + PvpAttributeDefinitions.BPK_NAME; + //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"; + //http end-points public static final String EIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/light/idp/post"; diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java index 47cfd3a9..aafe57e7 100644 --- a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java +++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java @@ -149,6 +149,32 @@ public class EidasProxyServiceController extends AbstractController implements I } + @Override + public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, + IRequest protocolRequest) throws Throwable { + + //TODO: implement error handling for eIDAS Node communication + 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; + + } /** * Validate incoming eIDAS request. @@ -180,9 +206,12 @@ public class EidasProxyServiceController extends AbstractController implements I try { String spCountry = eidasRequest.getSpCountryCode(); Map spConfigMap = new HashMap<>(); + + //TODO: how we get the EntityId from eIDAS connector? spConfigMap.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID, spCountry, eidasRequest.getSpType())); + ServiceProviderConfiguration spConfig = new ServiceProviderConfiguration(spConfigMap, authConfig); final String ccCountry = authConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, @@ -198,35 +227,7 @@ public class EidasProxyServiceController extends AbstractController implements I } catch (EaafException e) { throw new EidasProxyServiceException(ERROR_04, new Object[] {e.getMessage()}, e); - } - - } - - @Override - public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, - IRequest protocolRequest) throws Throwable { - - //TODO: implement error handling for eIDAS Node communication - 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; - + } } } diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java index 3ff35ac9..c51db460 100644 --- a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java +++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java @@ -1,18 +1,53 @@ 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.connector.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.gv.egiz.eaaf.core.api.IRequest; +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.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 * */ @@ -20,33 +55,178 @@ import lombok.extern.slf4j.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)); + + // put request into shared cache + final BinaryLightToken token = putResponseInCommunicationCache(lightRespBuilder.build()); + final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token); + + // 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, tokenBase64); + + return sloInformation; + + } catch (ServletException | IOException | GuiBuildException e) { + throw new EidasProxyServiceException("eidas.proxyservice.06", null, e); + + } - - return null; - } 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) { + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { return true; - + } @Override public String getDefaultActionName() { return PROXYSERVICE_AUTH_ACTION_NAME; + + } + + + @PostConstruct + private void checkConfiguration() { + //TODO: validate configuration on start-up } + + + private ImmutableAttributeMap buildAttributesFromAuthData(IAuthData authData) { + 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, + authData.getGenericData(MsProxyServiceConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class)) + .put(attrDefFamilyName, authData.getFamilyName()) + .put(attrDefGivenName, authData.getGivenName()) + .put(attrDefDateOfBirth, authData.getFormatedDateOfBirth()); + + 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 void forwardToEidasProxy(IRequest pendingReq, HttpServletRequest httpReq, + HttpServletResponse httpResp, String tokenBase64) throws EaafConfigurationException, IOException, + GuiBuildException { + // 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"); + + } + + } } diff --git a/eidas_modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties b/eidas_modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties index 0437554b..5c4c51b9 100644 --- a/eidas_modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties +++ b/eidas_modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties @@ -3,5 +3,6 @@ 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 Service-Provider country-code in Authn. request. Authentication not possible +eidas.proxyservice.06=Can not build eIDAS Proxy-Service response. Authentication FAILED. eidas.proxyservice.99=Internal error during eIDAS Proxy-Service authentication \ No newline at end of file diff --git a/eidas_modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java b/eidas_modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java index eb5280b3..96429d71 100644 --- a/eidas_modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java +++ b/eidas_modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java @@ -5,10 +5,13 @@ import static org.junit.Assert.assertThrows; import java.net.URISyntaxException; 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.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -26,6 +29,7 @@ import org.springframework.web.context.request.ServletRequestAttributes; import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyConfigMap; import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummySpConfiguration; import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask; +import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants; 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; @@ -35,6 +39,7 @@ 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.light.impl.LightRequest; @RunWith(SpringJUnit4ClassRunner.class) @PrepareForTest(CreateIdentityLinkTask.class) @@ -65,6 +70,9 @@ public class ProxyServiceAuthenticationActionTest { RequestContextHolder.resetRequestAttributes(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint", + "http://eidas.proxy/endpoint"); + final Map spConfig = new HashMap<>(); spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp"); spConfig.put("target", "urn:publicid:gv.at:cdid+XX"); @@ -76,6 +84,17 @@ public class ProxyServiceAuthenticationActionTest { pendingReq.initialize(httpReq, basicConfig); pendingReq.setOnlineApplicationConfiguration(oaParam); + 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()); + } @Test @@ -88,16 +107,35 @@ public class ProxyServiceAuthenticationActionTest { Assert.assertEquals("wrong errorCode", "eidas.proxyservice.99", exception.getErrorId()); } + + @Test + public void missingForwardUrl() { + Map attr = new HashMap<>(); + attr.put(MsProxyServiceConstants.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"); + 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 dummyResponseActionTest() throws EaafException { - IAuthData authData = generateDummyAuthData(); + Map attr = new HashMap<>(); + attr.put(MsProxyServiceConstants.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"); //perform test SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData); //validate state - Assert.assertNull("Result should be not null", result); + Assert.assertNotNull("Result should be not null", result); } @@ -112,6 +150,12 @@ public class ProxyServiceAuthenticationActionTest { } private IAuthData generateDummyAuthData() { + return generateDummyAuthData(Collections.emptyMap(), EaafConstants.EIDAS_LOA_LOW, + RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1940-01-01"); + + } + + private IAuthData generateDummyAuthData(Map attrs, String loa, String familyName, String givenName, String dateOfBirth) { return new IAuthData() { @Override @@ -176,26 +220,28 @@ public class ProxyServiceAuthenticationActionTest { @Override public String getGivenName() { - // TODO Auto-generated method stub - return null; + return givenName; } @Override public T getGenericData(String key, Class clazz) { - // TODO Auto-generated method stub - return null; + if (attrs.containsKey(key)) { + return (T) attrs.get(key); + + } else { + return null; + } + } @Override public String getFormatedDateOfBirth() { - // TODO Auto-generated method stub - return null; + return dateOfBirth; } @Override public String getFamilyName() { - // TODO Auto-generated method stub - return null; + return familyName; } @Override @@ -212,8 +258,8 @@ public class ProxyServiceAuthenticationActionTest { @Override public String getEidasQaaLevel() { - // TODO Auto-generated method stub - return null; + return loa; + } @Override diff --git a/eidas_modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties b/eidas_modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties index b03e2c81..4f3b82b5 100644 --- a/eidas_modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties +++ b/eidas_modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties @@ -1,3 +1,6 @@ ## Basic service configuration eidas.ms.context.url.prefix=http://localhost -eidas.ms.context.url.request.validation=false \ No newline at end of file +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/eidas_modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml b/eidas_modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml index 6a1505f4..2c16d796 100644 --- a/eidas_modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml +++ b/eidas_modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml @@ -16,6 +16,9 @@ + + test test-jar
+ + at.gv.egiz.eaaf + eaaf_module_pvp2_core + ${eaaf-core.version} + test + test-jar + + + at.gv.egiz.eaaf + eaaf_module_pvp2_idp + ${eaaf-core.version} + test + test-jar + at.gv.egiz.eaaf eaaf_module_pvp2_sp ${eaaf-core.version} test + test-jar at.gv.egiz.eaaf -- cgit v1.2.3