From e8e75813ab549d03b0ac482fe0e1e86ee660b8b0 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Fri, 11 Mar 2022 11:49:05 +0100 Subject: chore(proxy): add module for stand-alone ms-specific proxy-service application --- .../MsConnectorSpringResourceProviderTest.java | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/MsConnectorSpringResourceProviderTest.java (limited to 'ms_specific_proxyservice/src/test/java') diff --git a/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/MsConnectorSpringResourceProviderTest.java b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/MsConnectorSpringResourceProviderTest.java new file mode 100644 index 00000000..2da6b316 --- /dev/null +++ b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/MsConnectorSpringResourceProviderTest.java @@ -0,0 +1,56 @@ +package at.asitplus.eidas.specific.proxy.test; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + +import at.asitplus.eidas.specific.proxy.MsSpecificEidasProxySpringResourceProvider; +import at.gv.egiz.eaaf.core.test.TestConstants; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class MsConnectorSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final MsSpecificEidasProxySpringResourceProvider test = + new MsSpecificEidasProxySpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + MsSpecificEidasProxySpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} -- cgit v1.2.3 From 7f0a925a72dc9841280e66fcba1515af62b9efdf Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Fri, 3 Jun 2022 15:24:01 +0200 Subject: test(core): add smoke test with full eIDAS OutGoing login and error-handling --- .../src/main/resources/application.properties | 3 - .../eidas_v2_auth_ref_impl_config.beans.xml | 39 -- .../eidas_v2_auth_ref_impl_config.beans.xml | 39 ++ .../MsProxyServiceSpringResourceProvider.java | 5 +- .../resources/spring/eidas_proxy-service.beans.xml | 7 + .../spring/SpringTest-context_basic_test.xml | 8 - .../proxy/pvp/PvpEndPointConfiguration.java | 154 +++++++ .../src/main/resources/application.properties | 1 + .../main/resources/specific_eIDAS_proxy.beans.xml | 4 +- .../proxy/test/FullStartUpAndProcessTest.java | 480 +++++++++++++++++++++ .../config/eIDAS/additional-attributes.xml | 39 ++ .../resources/config/eIDAS/eidas-attributes.xml | 376 ++++++++++++++++ .../config/eIDAS/igniteSpecificCommunication.xml | 109 +++++ .../specificCommunicationDefinitionConnector.xml | 37 ++ ...specificCommunicationDefinitionProxyservice.xml | 37 ++ .../config/junit_config_1_springboot.properties | 116 +++++ .../src/test/resources/config/keys/Metadata.pem | 18 + .../src/test/resources/config/keys/junit.jks | Bin 0 -> 3980 bytes .../src/test/resources/config/keys/junit_test.jks | Bin 0 -> 8410 bytes .../src/test/resources/config/keys/teststore.jks | Bin 0 -> 2028 bytes .../src/test/resources/config/logback_config.xml | 102 +++++ .../config/properties/messages.properties | 0 .../config/properties/messages_de.properties | 0 .../config/properties/messages_en.properties | 0 .../config/templates/eidas_node_forward.html | 36 ++ .../src/test/resources/config/templates/error.html | 53 +++ .../resources/config/templates/error_message.html | 37 ++ .../config/templates/pvp2_post_binding.html | 36 ++ .../test/resources/config/webcontent/autocommit.js | 5 + .../resources/config/webcontent/css/css_error.css | 26 ++ .../config/webcontent/img/ajax-loader.gif | Bin 0 -> 673 bytes .../src/test/resources/data/Response_with_EID.xml | 49 +++ .../data/idp_metadata_classpath_entity.xml | 146 +++++++ 33 files changed, 1910 insertions(+), 52 deletions(-) delete mode 100644 modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml create mode 100644 modules/core_commons_eidas/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml create mode 100644 ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/pvp/PvpEndPointConfiguration.java create mode 100644 ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java create mode 100644 ms_specific_proxyservice/src/test/resources/config/eIDAS/additional-attributes.xml create mode 100644 ms_specific_proxyservice/src/test/resources/config/eIDAS/eidas-attributes.xml create mode 100644 ms_specific_proxyservice/src/test/resources/config/eIDAS/igniteSpecificCommunication.xml create mode 100644 ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionConnector.xml create mode 100644 ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionProxyservice.xml create mode 100644 ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties create mode 100644 ms_specific_proxyservice/src/test/resources/config/keys/Metadata.pem create mode 100644 ms_specific_proxyservice/src/test/resources/config/keys/junit.jks create mode 100644 ms_specific_proxyservice/src/test/resources/config/keys/junit_test.jks create mode 100644 ms_specific_proxyservice/src/test/resources/config/keys/teststore.jks create mode 100644 ms_specific_proxyservice/src/test/resources/config/logback_config.xml create mode 100644 ms_specific_proxyservice/src/test/resources/config/properties/messages.properties create mode 100644 ms_specific_proxyservice/src/test/resources/config/properties/messages_de.properties create mode 100644 ms_specific_proxyservice/src/test/resources/config/properties/messages_en.properties create mode 100644 ms_specific_proxyservice/src/test/resources/config/templates/eidas_node_forward.html create mode 100644 ms_specific_proxyservice/src/test/resources/config/templates/error.html create mode 100644 ms_specific_proxyservice/src/test/resources/config/templates/error_message.html create mode 100644 ms_specific_proxyservice/src/test/resources/config/templates/pvp2_post_binding.html create mode 100644 ms_specific_proxyservice/src/test/resources/config/webcontent/autocommit.js create mode 100644 ms_specific_proxyservice/src/test/resources/config/webcontent/css/css_error.css create mode 100644 ms_specific_proxyservice/src/test/resources/config/webcontent/img/ajax-loader.gif create mode 100644 ms_specific_proxyservice/src/test/resources/data/Response_with_EID.xml create mode 100644 ms_specific_proxyservice/src/test/resources/data/idp_metadata_classpath_entity.xml (limited to 'ms_specific_proxyservice/src/test/java') diff --git a/connector/src/main/resources/application.properties b/connector/src/main/resources/application.properties index e062c32b..700f4d74 100644 --- a/connector/src/main/resources/application.properties +++ b/connector/src/main/resources/application.properties @@ -159,9 +159,6 @@ eidas.ms.auth.eIDAS.zmrclient.debug.logfullmessages=false #eidas.ms.auth.eIDAS.ernpclient.ssl.keyStore.password=password #eidas.ms.auth.eIDAS.ernpclient.ssl.key.alias=meta #eidas.ms.auth.eIDAS.ernpclient.ssl.key.password=password -eidas.ms.client.http.connection.timeout.request=15 -eidas.ms.client.http.connection.timeout.socket=30 - # SAML2 ID Austria client for matching #eidas.ms.modules.idaustriaclient.keystore.type=jks diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml b/modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml deleted file mode 100644 index cde9687e..00000000 --- a/modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/modules/core_commons_eidas/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml b/modules/core_commons_eidas/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml new file mode 100644 index 00000000..cde9687e --- /dev/null +++ b/modules/core_commons_eidas/src/main/resources/eidas_v2_auth_ref_impl_config.beans.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java index d36e4712..571ad8ab 100644 --- a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java +++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java @@ -45,8 +45,11 @@ public class MsProxyServiceSpringResourceProvider implements SpringResourceProvi public Resource[] getResourcesToLoad() { final ClassPathResource eidasProxyServiceConfig = new ClassPathResource("/spring/eidas_proxy-service.beans.xml", MsProxyServiceSpringResourceProvider.class); + final ClassPathResource eidasRefImplConfig = new ClassPathResource("/eidas_v2_auth_ref_impl_config.beans.xml", + MsProxyServiceSpringResourceProvider.class); + - return new Resource[] { eidasProxyServiceConfig }; + return new Resource[] { eidasProxyServiceConfig, eidasRefImplConfig }; } } diff --git a/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml b/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml index 2055b5a9..1eb33e93 100644 --- a/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml +++ b/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml @@ -24,5 +24,12 @@ + + + + \ No newline at end of file diff --git a/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml index 08b25f0f..0b7540f5 100644 --- a/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml +++ b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml @@ -31,12 +31,4 @@ value="src/test/resources/config/additional-attributes.xml" /> - - - - - \ No newline at end of file diff --git a/ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/pvp/PvpEndPointConfiguration.java b/ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/pvp/PvpEndPointConfiguration.java new file mode 100644 index 00000000..20caf7e5 --- /dev/null +++ b/ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/pvp/PvpEndPointConfiguration.java @@ -0,0 +1,154 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.asitplus.eidas.specific.proxy.pvp; + +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration; +import org.opensaml.saml.saml2.metadata.EmailAddress; +import org.opensaml.saml.saml2.metadata.GivenName; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.OrganizationDisplayName; +import org.opensaml.saml.saml2.metadata.OrganizationName; +import org.opensaml.saml.saml2.metadata.OrganizationURL; +import org.opensaml.saml.saml2.metadata.SurName; +import org.springframework.beans.factory.annotation.Autowired; + +import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +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.modules.pvp2.api.IPvp2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PvpEndPointConfiguration implements IPvp2BasicConfiguration { + private static final String DEFAULT_XML_LANG = "en"; + + @Autowired(required = true) + IConfiguration basicConfiguration; + + @Override + public String getIdpEntityId(String authUrl) throws EaafException { + return removePostFix(authUrl) + MsEidasNodeConstants.ENDPOINT_PVP_METADATA; + + } + + @Override + public String getIdpSsoPostService(String authUrl) throws EaafException { + return removePostFix(authUrl) + MsEidasNodeConstants.ENDPOINT_PVP_POST; + + } + + @Override + public String getIdpSsoRedirectService(String authUrl) throws EaafException { + return removePostFix(authUrl) + MsEidasNodeConstants.ENDPOINT_PVP_REDIRECT; + + } + + @Override + public String getIdpSsoSoapService(String extractAuthUrlFromRequest) throws EaafException { + log.warn("PVP S-Profile End-Point does NOT support SOAP Binding"); + return null; + + } + + @Override + public List getIdpContacts() throws EaafException { + final ContactPerson contactPerson = Saml2Utils.createSamlObject(ContactPerson.class); + final GivenName givenName = Saml2Utils.createSamlObject(GivenName.class); + final SurName surname = Saml2Utils.createSamlObject(SurName.class); + final EmailAddress emailAddress = Saml2Utils.createSamlObject(EmailAddress.class); + + givenName.setValue(getAndVerifyFromConfiguration( + MsEidasNodeConstants.CONFIG_PROPS_METADATA_CONTACT_GIVENNAME)); + surname.setValue(getAndVerifyFromConfiguration( + MsEidasNodeConstants.CONFIG_PROPS_METADATA_CONTACT_SURNAME)); + emailAddress.setURI(getAndVerifyFromConfiguration( + MsEidasNodeConstants.CONFIG_PROPS_METADATA_CONTACT_EMAIL)); + + contactPerson.setType(ContactPersonTypeEnumeration.TECHNICAL); + contactPerson.setGivenName(givenName); + contactPerson.setSurName(surname); + contactPerson.getEmailAddresses().add(emailAddress); + + return Arrays.asList(contactPerson); + + } + + @Override + public Organization getIdpOrganisation() throws EaafException { + final Organization organisation = Saml2Utils.createSamlObject(Organization.class); + final OrganizationName orgName = Saml2Utils.createSamlObject(OrganizationName.class); + final OrganizationDisplayName orgDisplayName = Saml2Utils.createSamlObject(OrganizationDisplayName.class); + final OrganizationURL orgUrl = Saml2Utils.createSamlObject(OrganizationURL.class); + + orgName.setXMLLang(DEFAULT_XML_LANG); + orgName.setValue(getAndVerifyFromConfiguration( + MsEidasNodeConstants.CONFIG_PROPS_METADATA_ORGANISATION_NAME)); + + orgDisplayName.setXMLLang(DEFAULT_XML_LANG); + orgDisplayName.setValue(getAndVerifyFromConfiguration( + MsEidasNodeConstants.CONFIG_PROPS_METADATA_ORGANISATION_FRIENDLYNAME)); + + orgUrl.setXMLLang(DEFAULT_XML_LANG); + orgUrl.setURI(getAndVerifyFromConfiguration( + MsEidasNodeConstants.CONFIG_PROPS_METADATA_ORGANISATION_URL)); + + + organisation.getOrganizationNames().add(orgName); + organisation.getDisplayNames().add(orgDisplayName); + organisation.getURLs().add(orgUrl); + + return organisation; + } + + @Override + public IConfiguration getBasicConfiguration() { + return basicConfiguration; + } + + private String removePostFix(String url) { + if (url != null && url.endsWith("/")) { + return url.substring(0, url.length() - 1); + } else { + return url; + } + } + + private String getAndVerifyFromConfiguration(String configKey) throws EaafConfigurationException { + final String value = basicConfiguration.getBasicConfiguration(configKey); + if (StringUtils.isEmpty(value)) { + throw new EaafConfigurationException("config.08", + new Object[] {configKey}); + + } + + return value; + } +} diff --git a/ms_specific_proxyservice/src/main/resources/application.properties b/ms_specific_proxyservice/src/main/resources/application.properties index 9f1b68e2..7d8c199f 100644 --- a/ms_specific_proxyservice/src/main/resources/application.properties +++ b/ms_specific_proxyservice/src/main/resources/application.properties @@ -73,6 +73,7 @@ eidas.ms.configuration.pvp.enable.entitycategories=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= +eidas.ms.auth.eIDAS.node_v2.forward.method=POST # Mandate configuration eidas.ms.auth.eIDAS.proxy.mandates.enabled=false diff --git a/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml b/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml index c5312751..5633cb0e 100644 --- a/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml +++ b/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml @@ -12,6 +12,8 @@ http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> - + + \ No newline at end of file diff --git a/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java new file mode 100644 index 00000000..bc6f5317 --- /dev/null +++ b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java @@ -0,0 +1,480 @@ +package at.asitplus.eidas.specific.proxy.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Base64; +import java.util.Map; +import java.util.TimeZone; +import java.util.Timer; +import java.util.UUID; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.ignite.Ignition; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.InitializationException; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.core.io.ResourceLoader; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.Base64Utils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.google.common.collect.ImmutableSet; + +import at.asitplus.eidas.specific.modules.auth.idaustria.controller.IdAustriaAuthSignalController; +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.core.eidas.EidasConstants; +import at.asitplus.eidas.specific.modules.core.eidas.service.EidasAttributeRegistry; +import at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController; +import at.gv.egiz.components.spring.api.SpringBootApplicationContextInitializer; +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; +import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; +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.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication; +import eu.eidas.auth.commons.EidasParameterKeys; +import eu.eidas.auth.commons.attribute.AttributeValue; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.light.ILightResponse; +import eu.eidas.auth.commons.light.impl.LightRequest; +import eu.eidas.auth.commons.tx.BinaryLightToken; +import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames; +import eu.eidas.specificcommunication.protocol.SpecificCommunicationService; +import lombok.SneakyThrows; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +@ContextConfiguration(initializers = { + org.springframework.boot.context.config.DelegatingApplicationContextInitializer.class, + SpringBootApplicationContextInitializer.class + }) +@TestPropertySource(locations = { "file:src/test/resources/config/junit_config_1_springboot.properties" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@ActiveProfiles(profiles = {"JUNIT", "jUnitTestMode"}) +public class FullStartUpAndProcessTest { + + private static final String METADATA_PATH = "classpath:/data/idp_metadata_classpath_entity.xml"; + private static final String FINAL_REDIRECT = "https://localhost/ms_proxy/public/secure/finalizeAuthProtocol?pendingid="; + private static final String ERROR_REDIRECT = "https://localhost/ms_proxy/public/secure/errorHandling?errorid="; + + + @Autowired private WebApplicationContext wac; + + @Autowired private ResourceLoader resourceLoader; + @Autowired private EidasAttributeRegistry attrRegistry; + + @Autowired private IdAustriaAuthSignalController idAustriaEndpoint; + @Autowired private IdAustriaAuthMetadataProvider idAustriaMetadata; + @Autowired private IdAustriaAuthCredentialProvider credentialProvider; + + @Autowired private EidasProxyServiceController eidasProxyEndpoint; + @Autowired private ProtocolFinalizationController finalize; + + @Autowired private IStatusMessenger messager; + + /** + * jUnit class initializer. + * @throws InterruptedException In case of an error + * @throws ComponentInitializationException In case of an error + * @throws InitializationException In case of an error + * + */ + @BeforeClass + @SneakyThrows + public static void classInitializer() { + final String current = new java.io.File(".").toURI().toString(); + System.clearProperty("eidas.ms.configuration"); + + //eIDAS Ref. Impl. properties + System.setProperty("EIDAS_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_CONNECTOR_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_PROXY_SERVICE_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test shut-down. + * + * @throws Exception In case of an error + */ + @AfterClass + @SneakyThrows + public static void closeIgniteNode() { + System.out.println("Closiong Ignite Node ... "); + Ignition.stopAll(true); + + //set Ignite-node holder to 'null' because static holders are shared between different tests + final Field field = IgniteInstanceInitializerSpecificCommunication.class.getDeclaredField("instance"); + field.setAccessible(true); + field.set(null, null); + + } + + /** + * jUnit test set-up. + * + * + */ + @Before + public void setup() throws IOException { + DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac); + @SuppressWarnings("rawtypes") + Map filters = wac.getBeansOfType(FilterRegistrationBean.class); + for (FilterRegistrationBean filter : filters.values()) { + if (filter.isEnabled()) { + builder.addFilter(filter.getFilter(), "/*"); + + } + } + + LogMessageProviderFactory.setStatusMessager(messager); + + } + + @Test + @SneakyThrows + public void simpleError() { + MockHttpServletRequest proxyHttpReq = new MockHttpServletRequest("POST", "https://localhost/ms_proxy"); + String spCountryCode = injectEidas2AuthnReq(proxyHttpReq); + MockHttpServletResponse proxyHttpResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(proxyHttpReq, proxyHttpResp)); + + injectIdAustriaSaml2Metadata(); + + + // send eIDAS Proxy-Service process hand-over + eidasProxyEndpoint.receiveEidasAuthnRequest(proxyHttpReq, proxyHttpResp); + + + // extract SAML2 AuthnRequest to IDA system + assertEquals("forward to finalization", 200, proxyHttpResp.getStatus()); + assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", proxyHttpResp.getContentType()); + String saml2ReqPage = proxyHttpResp.getContentAsString(); + assertNotNull("selectionPage is null", saml2ReqPage); + assertFalse("selectionPage is empty", saml2ReqPage.isEmpty()); + + String saml2ReqB64 = extractRequestToken(saml2ReqPage, "> attr = attributes.getAttributeValuesByNameUri(attrName); + assertNotNull("Attribute: " + attrName, attr); + assertFalse("Empty AttributeValue: " + attrName, attr.isEmpty()); + assertNotNull("AttributeValue: " + attrName, attr.asList().get(0)); + assertEquals("Wrong AttributeValue: " + attrName, expected, attr.asList().get(0).getValue()); + + } + + @SneakyThrows + private String validateSaml2Request(String saml2ReqB64, String spCountryCode) { + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + new ByteArrayInputStream(Base64Utils.decodeFromString(saml2ReqB64))); + + // check requested attributes + assertEquals("wrong number of extension elements", + 1, authnReq.getExtensions().getOrderedChildren().size()); + assertEquals("wrong number of requested attributes", + 4, authnReq.getExtensions().getOrderedChildren().get(0).getOrderedChildren().size()); + + return authnReq.getID(); + } + + @SneakyThrows + private String buildSaml2Response(String saml2ReqId) { + final Response response = initializeResponse( + "classpath:/data/idp_metadata_classpath_entity.xml", + "/data/Response_with_EID.xml", + credentialProvider.getMessageSigningCredential(), + true, saml2ReqId); + return Base64.getEncoder().encodeToString( + DomUtils.serializeNode(XMLObjectSupport.getMarshaller(response).marshall(response)).getBytes( + "UTF-8")); + + } + + private Response initializeResponse(String idpEntityId, String responsePath, EaafX509Credential credential, + boolean validConditions, String saml2ReqId) throws SamlSigningException, XMLParserException, UnmarshallingException, + Pvp2MetadataException { + + final Response response = (Response) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + FullStartUpAndProcessTest.class.getResourceAsStream(responsePath)); + response.setIssueInstant(Instant.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(idpEntityId); + response.setIssuer(issuer); + response.setInResponseTo(saml2ReqId); + + if (validConditions) { + response.getAssertions().get(0).getConditions().setNotOnOrAfter(Instant.now().plusSeconds(5*60)); + + } + + return Saml2Utils.signSamlObject(response, credential, true); + } + + @SneakyThrows + private void injectIdAustriaSaml2Metadata() { + final org.springframework.core.io.Resource resource = resourceLoader.getResource(METADATA_PATH); + Timer timer = new Timer("PVP metadata-resolver refresh"); + ResourceBackedMetadataResolver fileSystemResolver = + new ResourceBackedMetadataResolver(timer, new OpenSaml3ResourceAdapter(resource)); + fileSystemResolver.setId("test"); + fileSystemResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool()); + fileSystemResolver.initialize(); + idAustriaMetadata.addMetadataResolverIntoChain(fileSystemResolver); + + + } + + private String extractRequestToken(String selectionPage, String selector) { + int start = selectionPage.indexOf(selector); + assertTrue("find no starting element of selector", start > 0); + int end = selectionPage.indexOf("\"", start + selector.length()); + assertTrue("find no end tag", end > 0); + return selectionPage.substring(start + selector.length(), end); + + } + + @SneakyThrows + private String injectEidas2AuthnReq(MockHttpServletRequest proxyHttpReq) { + String spCountryCode = "XX"; + LightRequest.Builder authnReqBuilder = LightRequest.builder() + .id(UUID.randomUUID().toString()) + .issuer(RandomStringUtils.randomAlphabetic(10)) + .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase()) + .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH) + .spCountryCode(spCountryCode) + .spType("public") + .requestedAttributes(ImmutableAttributeMap.builder() + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first()) + .build()); + + final SpecificCommunicationService springManagedSpecificConnectorCommunicationService = + (SpecificCommunicationService) wac.getBean( + SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE.toString()); + BinaryLightToken token = springManagedSpecificConnectorCommunicationService.putRequest(authnReqBuilder.build()); + proxyHttpReq.addParameter(EidasParameterKeys.TOKEN.toString(), Base64Utils.encodeToString(token.getTokenBytes())); + + return spCountryCode; + + } + +} diff --git a/ms_specific_proxyservice/src/test/resources/config/eIDAS/additional-attributes.xml b/ms_specific_proxyservice/src/test/resources/config/eIDAS/additional-attributes.xml new file mode 100644 index 00000000..6510546e --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/eIDAS/additional-attributes.xml @@ -0,0 +1,39 @@ + + + + + + Dynamic attributes + + http://eidas.europa.eu/attributes/naturalperson/AdditionalAttribute + AdditionalAttribute + NaturalPerson + false + http://www.w3.org/2001/XMLSchema + string + xs + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/LegalAdditionalAttribute + LegalAdditionalAttribute + LegalPerson + false + http://www.w3.org/2001/XMLSchema + string + xs + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + diff --git a/ms_specific_proxyservice/src/test/resources/config/eIDAS/eidas-attributes.xml b/ms_specific_proxyservice/src/test/resources/config/eIDAS/eidas-attributes.xml new file mode 100644 index 00000000..cbae35db --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/eIDAS/eidas-attributes.xml @@ -0,0 +1,376 @@ + + + + + + eIDAS attributes + + http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier + PersonIdentifier + NaturalPerson + true + true + http://eidas.europa.eu/attributes/naturalperson + PersonIdentifierType + eidas-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName + FamilyName + NaturalPerson + true + true + http://eidas.europa.eu/attributes/naturalperson + CurrentFamilyNameType + eidas-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName + FirstName + NaturalPerson + true + true + http://eidas.europa.eu/attributes/naturalperson + CurrentGivenNameType + eidas-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/DateOfBirth + DateOfBirth + NaturalPerson + true + http://eidas.europa.eu/attributes/naturalperson + DateOfBirthType + eidas-natural + eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/BirthName + BirthName + NaturalPerson + false + true + http://eidas.europa.eu/attributes/naturalperson + BirthNameType + eidas-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth + PlaceOfBirth + NaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson + PlaceOfBirthType + eidas-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/CurrentAddress + CurrentAddress + NaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson + CurrentAddressType + eidas-natural + eu.eidas.auth.commons.protocol.eidas.impl.CurrentAddressAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/Gender + Gender + NaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson + GenderType + eidas-natural + eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier + LegalPersonIdentifier + LegalPerson + true + true + http://eidas.europa.eu/attributes/legalperson + LegalPersonIdentifierType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/LegalName + LegalName + LegalPerson + true + true + http://eidas.europa.eu/attributes/legalperson + LegalNameType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/LegalPersonAddress + LegalAddress + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + LegalPersonAddressType + eidas-legal + eu.eidas.auth.commons.protocol.eidas.impl.LegalAddressAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/VATRegistrationNumber + VATRegistration + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + VATRegistrationNumberType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/TaxReference + TaxReference + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + TaxReferenceType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/D-2012-17-EUIdentifier + D-2012-17-EUIdentifier + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + D-2012-17-EUIdentifierType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/LEI + LEI + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + LEIType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/EORI + EORI + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + EORIType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/SEED + SEED + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + SEEDType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/SIC + SIC + LegalPerson + false + http://eidas.europa.eu/attributes/legalperson + SICType + eidas-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/PersonIdentifier + RepresentativePersonIdentifier + RepresentativeNaturalPerson + false + true + http://eidas.europa.eu/attributes/naturalperson/representative + PersonIdentifierType + eidas-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/CurrentFamilyName + RepresentativeFamilyName + RepresentativeNaturalPerson + false + true + http://eidas.europa.eu/attributes/naturalperson/representative + CurrentFamilyNameType + eidas-reprentative-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/CurrentGivenName + RepresentativeFirstName + RepresentativeNaturalPerson + false + true + http://eidas.europa.eu/attributes/naturalperson/representative + CurrentGivenNameType + eidas-reprentative-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/DateOfBirth + RepresentativeDateOfBirth + RepresentativeNaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson/representative + DateOfBirthType + eidas-reprentative-natural + eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/BirthName + RepresentativeBirthName + RepresentativeNaturalPerson + false + true + http://eidas.europa.eu/attributes/naturalperson/representative + BirthNameType + eidas-reprentative-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/PlaceOfBirth + RepresentativePlaceOfBirth + RepresentativeNaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson/representative + PlaceOfBirthType + eidas-reprentative-natural + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/CurrentAddress + RepresentativeCurrentAddress + RepresentativeNaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson/representative + CurrentAddressType + eidas-reprentative-natural + eu.eidas.auth.commons.protocol.eidas.impl.RepvCurrentAddressAttributeValueMarshaller + + http://eidas.europa.eu/attributes/naturalperson/representative/Gender + RepresentativeGender + RepresentativeNaturalPerson + false + http://eidas.europa.eu/attributes/naturalperson/representative + GenderType + eidas-reprentative-natural + eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonIdentifier + RepresentativeLegalPersonIdentifier + RepresentativeLegalPerson + false + true + http://eidas.europa.eu/attributes/legalperson/representative + LegalPersonIdentifierType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/LegalName + RepresentativeLegalName + RepresentativeLegalPerson + false + true + http://eidas.europa.eu/attributes/legalperson/representative + LegalNameType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress + RepresentativeLegalAddress + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + LegalPersonAddressType + eidas-reprentative-legal + eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber + RepresentativeVATRegistration + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + VATRegistrationNumberType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/TaxReference + RepresentativeTaxReference + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + TaxReferenceType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/D-2012-17-EUIdentifier + RepresentativeD-2012-17-EUIdentifier + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + D-2012-17-EUIdentifierType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/LEI + RepresentativeLEI + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + LEIType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/EORI + RepresentativeEORI + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + EORIType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/SEED + RepresentativeSEED + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + SEEDType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/SIC + RepresentativeSIC + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + SICType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress + RepresentativeLegalAddress + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + LegalPersonAddressType + eidas-reprentative-legal + eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller + + http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber + RepresentativeVATRegistration + RepresentativeLegalPerson + false + http://eidas.europa.eu/attributes/legalperson/representative + VATRegistrationNumberType + eidas-reprentative-legal + eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller + + + diff --git a/ms_specific_proxyservice/src/test/resources/config/eIDAS/igniteSpecificCommunication.xml b/ms_specific_proxyservice/src/test/resources/config/eIDAS/igniteSpecificCommunication.xml new file mode 100644 index 00000000..f817f5a4 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/eIDAS/igniteSpecificCommunication.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionConnector.xml b/ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionConnector.xml new file mode 100644 index 00000000..d1fc042d --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionConnector.xml @@ -0,0 +1,37 @@ + + + + + + + specificCommunicationDefinitionConnectorRequest + specificConnector + + + mySecretConnectorRequest + SHA-256 + + + specificCommunicationDefinitionConnectorResponse + specificConnector + + + mySecretConnectorResponse + SHA-256 + + + 65535 + diff --git a/ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionProxyservice.xml b/ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionProxyservice.xml new file mode 100644 index 00000000..c8caf16b --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/eIDAS/specificCommunicationDefinitionProxyservice.xml @@ -0,0 +1,37 @@ + + + + + + true + + + specificCommunicationDefinitionProxyserviceRequest + specificProxyService + + mySecretProxyserviceRequest + SHA-256 + + + specificCommunicationDefinitionProxyserviceResponse + specificProxyService + + mySecretProxyserviceResponse + SHA-256 + + + 65535 + diff --git a/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties b/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties new file mode 100644 index 00000000..8cd77046 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties @@ -0,0 +1,116 @@ +## Set Spring-Boot profile-configuration to 2.3 style +spring.config.use-legacy-processing=true + +## ApplicationServer configuration +server.servlet.contextPath=/ms_proxyservice +#server.port=7080 + +app.build.artifactId=ms_proxyservice + + + +############################################################################# +## SpringBoot Admin client +spring.boot.admin.client.enabled=false + +############################################################################# +## SpringBoot Actuator +management.endpoints.web.exposure.include=health,info + +############################################################################# +## Common parts of MS-speccific eIDAS application configuration + +eidas.ms.context.url.prefix=https://localhost/ms_proxy/ +eidas.ms.context.url.request.validation=false +eidas.ms.core.configRootDir=file:./src/test/resources/config/ +eidas.ms.context.use.clustermode=true +eidas.ms.core.logging.level.info.errorcodes=auth.21 + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url= + + +##Specific logger configuration +eidas.ms.technicallog.write.MDS.into.techlog=true +eidas.ms.revisionlog.write.MDS.into.revisionlog=true +eidas.ms.revisionlog.logIPAddressOfUser=true + + +##Directory for static Web content +eidas.ms.webcontent.static.directory=webcontent/ +eidas.ms.webcontent.templates=templates/ +eidas.ms.webcontent.properties=properties/messages + + +## extended validation of pending-request Id's +eidas.ms.core.pendingrequestid.maxlifetime=300 +eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256 +eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret + + +## 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-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=http://localhost/EidasNode +eidas.ms.auth.eIDAS.node_v2.forward.method=POST + +# Mandate configuration +eidas.ms.auth.eIDAS.proxy.mandates.enabled=false +#eidas.ms.auth.eIDAS.proxy.mandates.profiles.natural.default= +#eidas.ms.auth.eIDAS.proxy.mandates.profiles.legal.default= + + +## special foreign eIDAS-Connector configuration +#eidas.ms.connector.0.uniqueID=https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata +#eidas.ms.connector.0.countryCode=CC +#eidas.ms.connector.0.mandates.enabled=false +#eidas.ms.connector.0.mandates.natural= +#eidas.ms.connector.0.mandates.legal= +#eidas.ms.connector.0.auth.idaustria.entityId= + + +## PVP2 S-Profile communication with ID Austria System +# EntityId and optional metadata of ID Austria System +eidas.ms.modules.idaustriaauth.idp.entityId=classpath:/data/idp_metadata_classpath_entity.xml +#eidas.ms.modules.idaustriaauth.idp.metadataUrl= + +# SAML2 client configuration +eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks +eidas.ms.modules.idaustriaauth.keystore.password=password +eidas.ms.modules.idaustriaauth.keystore.type=jks + +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 + +eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks +eidas.ms.modules.idaustriaauth.truststore.password=password +eidas.ms.modules.idaustriaauth.truststore.type=jks + + + diff --git a/ms_specific_proxyservice/src/test/resources/config/keys/Metadata.pem b/ms_specific_proxyservice/src/test/resources/config/keys/Metadata.pem new file mode 100644 index 00000000..b544c194 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/keys/Metadata.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A== +-----END CERTIFICATE----- diff --git a/ms_specific_proxyservice/src/test/resources/config/keys/junit.jks b/ms_specific_proxyservice/src/test/resources/config/keys/junit.jks new file mode 100644 index 00000000..59e6ad13 Binary files /dev/null and b/ms_specific_proxyservice/src/test/resources/config/keys/junit.jks differ diff --git a/ms_specific_proxyservice/src/test/resources/config/keys/junit_test.jks b/ms_specific_proxyservice/src/test/resources/config/keys/junit_test.jks new file mode 100644 index 00000000..ee6254a9 Binary files /dev/null and b/ms_specific_proxyservice/src/test/resources/config/keys/junit_test.jks differ diff --git a/ms_specific_proxyservice/src/test/resources/config/keys/teststore.jks b/ms_specific_proxyservice/src/test/resources/config/keys/teststore.jks new file mode 100644 index 00000000..fcc6400c Binary files /dev/null and b/ms_specific_proxyservice/src/test/resources/config/keys/teststore.jks differ diff --git a/ms_specific_proxyservice/src/test/resources/config/logback_config.xml b/ms_specific_proxyservice/src/test/resources/config/logback_config.xml new file mode 100644 index 00000000..bb3de3e8 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/logback_config.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + ${catalina.base}/logs/eIDAS_node.log + + %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n + + + 9999 + ${catalina.base}/logs/eIDAS_node.log.%i + + + 10000KB + + + + + ${catalina.base}/logs/eidas-ms-reversion.log + + %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n + + + 9999 + ${catalina.base}/logs/eidas-ms-reversion.log.%i + + + 10000KB + + + + + ${catalina.base}/logs/eidas-ms-reversion.log + + %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n + + + 9999 + ${catalina.base}/logs/eidas-ms-reversion.log.%i + + + 10000KB + + + + + ${catalina.base}/logs/eidas-ms-statistic.log + + %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n + + + 9999 + ${catalina.base}/logs/eidas-ms-statistic.log.%i + + + 10000KB + + + + + ${catalina.base}/logs/console.log + + %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n + + + 9999 + ${catalina.base}/logs/console.log.%i + + + 10000KB + + + + + %5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n + + + + + + + + + + + + + + + + + + + diff --git a/ms_specific_proxyservice/src/test/resources/config/properties/messages.properties b/ms_specific_proxyservice/src/test/resources/config/properties/messages.properties new file mode 100644 index 00000000..e69de29b diff --git a/ms_specific_proxyservice/src/test/resources/config/properties/messages_de.properties b/ms_specific_proxyservice/src/test/resources/config/properties/messages_de.properties new file mode 100644 index 00000000..e69de29b diff --git a/ms_specific_proxyservice/src/test/resources/config/properties/messages_en.properties b/ms_specific_proxyservice/src/test/resources/config/properties/messages_en.properties new file mode 100644 index 00000000..e69de29b diff --git a/ms_specific_proxyservice/src/test/resources/config/templates/eidas_node_forward.html b/ms_specific_proxyservice/src/test/resources/config/templates/eidas_node_forward.html new file mode 100644 index 00000000..6dffa34b --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/templates/eidas_node_forward.html @@ -0,0 +1,36 @@ + + + + + + + + +
Your login is being processed. Thank you for + waiting.
+ +
+
+ +
+ +
+ + + \ No newline at end of file diff --git a/ms_specific_proxyservice/src/test/resources/config/templates/error.html b/ms_specific_proxyservice/src/test/resources/config/templates/error.html new file mode 100644 index 00000000..21f589cd --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/templates/error.html @@ -0,0 +1,53 @@ + + + + + + +An error arise ... + + + +
+
+
+

Error Header

+ +
+

Error Information

+
+

Code :

+

Msg :

+
+
+ +
+

Timestamp:

+
+
+

Error:

+
+
+

Status:

+
+
+

Message:

+
+
+

Exception:

+
+
+

Trace:

+
+
+

Stacktrace:

+
+ +
+
+ + \ No newline at end of file diff --git a/ms_specific_proxyservice/src/test/resources/config/templates/error_message.html b/ms_specific_proxyservice/src/test/resources/config/templates/error_message.html new file mode 100644 index 00000000..caaf7136 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/templates/error_message.html @@ -0,0 +1,37 @@ + + + + + + + An error arise ... + + + +
+
+

Authentication error arise

+ +
+

Error Header

+ +
+

Error Information

+
+

Code :

+

Msg :

+
+ +
+ +
+

fullError

+
+ +
+
+ + \ No newline at end of file diff --git a/ms_specific_proxyservice/src/test/resources/config/templates/pvp2_post_binding.html b/ms_specific_proxyservice/src/test/resources/config/templates/pvp2_post_binding.html new file mode 100644 index 00000000..06b9b494 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/templates/pvp2_post_binding.html @@ -0,0 +1,36 @@ +## ## Velocity Template for SAML 2 HTTP-POST binding ## ## Velocity +##context may contain the following properties ## action - String - the +##action URL for the form ## RelayState - String - the relay state for the +##message ## SAMLRequest - String - the Base64 encoded SAML Request ## +##SAMLResponse - String - the Base64 encoded SAML Response + + + + + + + + +
Your login is being processed. Thank you for + waiting.
+ +
+
+ #if($RelayState) #end + #if($SAMLRequest) #end + #if($SAMLResponse) #end +
+ +
+ + + \ No newline at end of file diff --git a/ms_specific_proxyservice/src/test/resources/config/webcontent/autocommit.js b/ms_specific_proxyservice/src/test/resources/config/webcontent/autocommit.js new file mode 100644 index 00000000..d21a5651 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/webcontent/autocommit.js @@ -0,0 +1,5 @@ +function autoCommmit() { + document.forms[0].submit(); +} + +document.addEventListener('DOMContentLoaded', autoCommmit); \ No newline at end of file diff --git a/ms_specific_proxyservice/src/test/resources/config/webcontent/css/css_error.css b/ms_specific_proxyservice/src/test/resources/config/webcontent/css/css_error.css new file mode 100644 index 00000000..d772df43 --- /dev/null +++ b/ms_specific_proxyservice/src/test/resources/config/webcontent/css/css_error.css @@ -0,0 +1,26 @@ +@charset "utf-8"; + body { + padding-left: 5%; + background-color: #F9F9F9; + } + #page { + padding-top: 2%; + padding-right: 10%; + padding-left: 5%; + } + + .OA_header { + font-size: 2.1em; + padding-top:1%; + margin-bottom: 1%; + margin-top: 1%; + + } + + #alert_area { + float:left; + width: 100%; + } + + + diff --git a/ms_specific_proxyservice/src/test/resources/config/webcontent/img/ajax-loader.gif b/ms_specific_proxyservice/src/test/resources/config/webcontent/img/ajax-loader.gif new file mode 100644 index 00000000..f2a1bc0c Binary files /dev/null and b/ms_specific_proxyservice/src/test/resources/config/webcontent/img/ajax-loader.gif differ diff --git a/ms_specific_proxyservice/src/test/resources/data/Response_with_EID.xml b/ms_specific_proxyservice/src/test/resources/data/Response_with_EID.xml new file mode 100644 index 00000000..cf37a235 --- /dev/null +++ b/ms_specific_proxyservice/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/ms_proxy/sp/idaustria/eidas/metadata + + + + + http://eidas.europa.eu/LoA/high + + + + + 2.2 + + + http://eidas.europa.eu/LoA/high + + + AT + + + Mustermann + + + Max + + + 1940-01-01 + + + AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY= + + + + diff --git a/ms_specific_proxyservice/src/test/resources/data/idp_metadata_classpath_entity.xml b/ms_specific_proxyservice/src/test/resources/data/idp_metadata_classpath_entity.xml new file mode 100644 index 00000000..de565887 --- /dev/null +++ b/ms_specific_proxyservice/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 + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 3d9d419a40b17de1f94d46cbc2f5b345a93bff00 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Wed, 8 Jun 2022 12:32:16 +0200 Subject: feat(eidas): perform mapping between IDA and eIDAS attributes based on external configuration --- .../ms-proxyservice/misc/idaAttributeMapping.json | 170 +++++++++ .../SpRequiredAttributersAttributeBuilder.java | 63 ++++ .../tasks/ReceiveFromIdAustriaSystemTask.java | 30 +- .../tasks/RequestIdAustriaSystemTask.java | 6 + .../at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder | 1 + .../SpRequiredAttributersAttributeBuilderTest.java | 72 ++++ .../test/task/ReceiveAuthnResponseTaskTest.java | 24 +- .../test/task/RequestIdAustriaSystemTaskTest.java | 72 ++-- .../eidas/specific/core/MsEidasNodeConstants.java | 13 +- .../core/builder/AuthenticationDataBuilder.java | 185 ++++++++-- .../main/resources/specific_eIDAS_core.beans.xml | 3 - .../test/utils/AuthenticationDataBuilderTest.java | 311 +++++++++++++++- .../msproxyservice/dto/attributes/Type.java | 7 + .../protocol/ProxyServiceAuthenticationAction.java | 297 +++++++--------- .../service/ProxyEidasAttributeRegistry.java | 34 +- .../ProxyServiceAuthenticationActionTest.java | 217 +++++++++-- .../services/ProxyEidasAttributeRegistryTest.java | 35 ++ .../test/resources/config/idaAttributeMapping.json | 56 ++- .../resources/specific_eIDAS_connector.beans.xml | 3 + .../builder/ProxyAuthenticationDataBuilder.java | 38 ++ .../main/resources/specific_eIDAS_proxy.beans.xml | 3 + .../ProxyAuthenticationDataBuilderTest.java | 395 +++++++++++++++++++++ .../config/junit_config_1_springboot.properties | 2 +- pom.xml | 2 +- 24 files changed, 1713 insertions(+), 326 deletions(-) create mode 100644 basicConfig/ms-proxyservice/misc/idaAttributeMapping.json create mode 100644 modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/SpRequiredAttributersAttributeBuilder.java create mode 100644 modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/SpRequiredAttributersAttributeBuilderTest.java create mode 100644 ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/builder/ProxyAuthenticationDataBuilder.java create mode 100644 ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/builder/ProxyAuthenticationDataBuilderTest.java (limited to 'ms_specific_proxyservice/src/test/java') diff --git a/basicConfig/ms-proxyservice/misc/idaAttributeMapping.json b/basicConfig/ms-proxyservice/misc/idaAttributeMapping.json new file mode 100644 index 00000000..7c44b48a --- /dev/null +++ b/basicConfig/ms-proxyservice/misc/idaAttributeMapping.json @@ -0,0 +1,170 @@ +[ + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", + "idaAttribute": { + "basic": "urn:oid:1.2.40.0.10.2.1.1.149", + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.98" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName", + "idaAttribute": { + "basic": "urn:oid:2.5.4.42", + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.78" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName", + "idaAttribute": { + "basic": "urn:oid:1.2.40.0.10.2.1.1.261.20", + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.80" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/DateOfBirth", + "idaAttribute": { + "basic": "urn:oid:1.2.40.0.10.2.1.1.55", + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.82" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", + "idaAttribute": {}, + "type": { + "mds": false, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/BirthName", + "idaAttribute": {}, + "type": { + "mds": false, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.100" + }, + "addionalRequiredAttributes" : [ + "urn:oid:1.2.40.0.10.2.1.1.149", + "urn:oid:2.5.4.42", + "urn:oid:1.2.40.0.10.2.1.1.261.20", + "urn:oid:1.2.40.0.10.2.1.1.55" + ], + "type": { + "mds": true, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/legalperson/LegalName", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.84" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/representative/PersonIdentifier", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.149" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": true + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/representative/CurrentFamilyName", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.20" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": true + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/representative/CurrentGivenName", + "idaAttribute": { + "withMandates": "urn:oid:2.5.4.42" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": true + } + }, + { + "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/representative/DateOfBirth", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.55" + }, + "type": { + "mds": true, + "autoIncludeWithMandates": true + } + }, + { + "eidasAttribute": "*", + "idaAttribute": { + "basic": "urn:oid:1.2.40.0.10.2.1.1.261.32", + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.32" + }, + "type": { + "mds": false, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "*", + "idaAttribute": { + "basic": "urn:oid:1.2.40.0.10.2.1.1.261.108", + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.108" + }, + "type": { + "mds": false, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "*", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.68" + }, + "type": { + "mds": false, + "autoIncludeWithMandates": false + } + }, + { + "eidasAttribute": "*", + "idaAttribute": { + "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.106" + }, + "type": { + "mds": false, + "autoIncludeWithMandates": false + } + } +] diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/SpRequiredAttributersAttributeBuilder.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/SpRequiredAttributersAttributeBuilder.java new file mode 100644 index 00000000..61687088 --- /dev/null +++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/builder/attributes/SpRequiredAttributersAttributeBuilder.java @@ -0,0 +1,63 @@ +/* + * 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 org.apache.commons.lang3.StringUtils; + +import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration; +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; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SpRequiredAttributersAttributeBuilder + implements IAttributeBuilder, ExtendedPvpAttributeDefinitions { + + @Override + public String getName() { + return SP_REQUIRED_ATTRIBUTES_NAME; + } + + @Override + public ATT build(final ISpConfiguration oaParam, final IAuthData authData, + final IAttributeGenerator g) + throws AttributeBuilderException { + if (oaParam instanceof ServiceProviderConfiguration) { + return g.buildStringAttribute(SP_REQUIRED_ATTRIBUTES_FRIENDLY_NAME, SP_REQUIRED_ATTRIBUTES_NAME, + StringUtils.join(((ServiceProviderConfiguration)oaParam).getRequestedAttributes(), ",")); + + } else { + log.warn("Can not build attribute for required IDA attributes, because SP config-implementation does not match."); + return null; + + } + } + + @Override + public ATT buildEmpty(final IAttributeGenerator g) { + return g.buildEmptyAttribute(SP_REQUIRED_ATTRIBUTES_FRIENDLY_NAME, SP_REQUIRED_ATTRIBUTES_NAME); + + } + +} diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java index e486b851..17e0e0d5 100644 --- a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java +++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java @@ -16,7 +16,6 @@ import org.opensaml.saml.saml2.core.StatusCode; import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; import org.springframework.beans.factory.annotation.Autowired; -import at.asitplus.eidas.specific.core.MsEidasNodeConstants; import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants; import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthCredentialProvider; import at.asitplus.eidas.specific.modules.auth.idaustria.utils.IdAustriaAuthMetadataProvider; @@ -234,8 +233,7 @@ public class ReceiveFromIdAustriaSystemTask extends AbstractAuthServletTask { // inject all attributes into session final Set includedAttrNames = extractor.getAllIncludeAttributeNames(); for (final String attrName : includedAttrNames) { - injectAuthInfosIntoSession(session, attrName, - extractor.getSingleAttributeValue(attrName)); + injectAuthInfosIntoSession(session, attrName, extractor.getSingleAttributeValue(attrName)); } @@ -306,31 +304,11 @@ public class ReceiveFromIdAustriaSystemTask extends AbstractAuthServletTask { private void injectAuthInfosIntoSession(AuthProcessDataWrapper session, String attrName, String attrValue) throws EaafStorageException, IOException { log.trace("Inject attribute: {} with value: {} into AuthSession", attrName, attrValue); - log.debug("Inject attribute: {} into AuthSession", attrName); - if (PvpAttributeDefinitions.BPK_NAME.equals(attrName)) { - log.trace("Find bPK attribute. Extract eIDAS identifier ... "); - session.setGenericDataToSession(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, - extractBpkFromResponse(attrValue)); - - } else { - session.setGenericDataToSession(attrName, attrValue); - - } - + log.debug("Inject attribute: {} into AuthSession", attrName); + 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 { diff --git a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java index 66aadde6..bbe9b45f 100644 --- a/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java +++ b/modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java @@ -160,6 +160,12 @@ public class RequestIdAustriaSystemTask extends AbstractAuthServletTask { injectAttribute(attributs, PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, selectHighestLoa(pendingReq.getServiceProviderConfiguration().getRequiredLoA())); + // set list of IDA attributes as attribute + injectAttribute(attributs, ExtendedPvpAttributeDefinitions.SP_REQUIRED_ATTRIBUTES_NAME, + StringUtils.join( + pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).getRequestedAttributes(), + ",")); + //set ProviderName if available String providerName = ((ProxyServicePendingRequest)pendingReq).getEidasRequest().getProviderName(); if (StringUtils.isNotEmpty(providerName)) { diff --git a/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder b/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder index 65e9482c..3b20d687 100644 --- a/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder +++ b/modules/authmodule_id-austria/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder @@ -1 +1,2 @@ at.asitplus.eidas.specific.modules.auth.idaustria.builder.attributes.EidasConnecorUniqueIdAttributeBuilder +at.asitplus.eidas.specific.modules.auth.idaustria.builder.attributes.SpRequiredAttributersAttributeBuilder diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/SpRequiredAttributersAttributeBuilderTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/SpRequiredAttributersAttributeBuilderTest.java new file mode 100644 index 00000000..2fe420df --- /dev/null +++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/builder/attributes/SpRequiredAttributersAttributeBuilderTest.java @@ -0,0 +1,72 @@ +package at.asitplus.eidas.specific.modules.auth.idaustria.test.builder.attributes; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.internal.util.collections.Sets; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration; +import at.asitplus.eidas.specific.modules.auth.idaustria.builder.attributes.SpRequiredAttributersAttributeBuilder; +import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.impl.idp.auth.attributes.AbstractAttributeBuilderTest; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyConfiguration; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { + "/spring/SpringTest-context_basic_mapConfig.xml", + "/spring/SpringTest-context_basic_test.xml", +}) +public class SpRequiredAttributersAttributeBuilderTest extends AbstractAttributeBuilderTest { + +private final IAttributeBuilder attrBuilder = new SpRequiredAttributersAttributeBuilder(); + + @Test + public void attributeName() { + Assert.assertEquals("Wrong attribute name", + "urn:eidgvat:attributes.RequiredAttributes", attrBuilder.getName()); + + } + + @Test + public void checkEmptyAttribute() { + String value = attrBuilder.buildEmpty(gen); + Assert.assertNull("Attr. not null", value); + + } + + @Test + public void withWrongSpConfig() throws AttributeBuilderException, Exception { + String value = attrBuilder.build(spConfig, buildAuthData(), gen); + Assert.assertNull("Attr. not null", value); + + } + + @Test + public void withAttributeValue() throws AttributeBuilderException, Exception { + ServiceProviderConfiguration sp = new ServiceProviderConfiguration(spConfigMap, new DummyConfiguration()); + sp.setRequestedAttributes(Sets.newSet( + "aabbccdd", + RandomStringUtils.randomAlphanumeric(10), + PvpAttributeDefinitions.BIRTHDATE_NAME)); + + + String value = attrBuilder.build(sp, buildAuthData(), gen); + + List elements = KeyValueUtils.getListOfCsvValues(value); + assertEquals("wrong number of attributes", sp.getRequestedAttributes().size(), elements.size()); + sp.getRequestedAttributes().forEach( + el -> elements.contains(el)); + + } + +} diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java index c452fe22..c3be6dad 100644 --- a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java +++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java @@ -36,7 +36,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import at.asitplus.eidas.specific.core.MsEidasNodeConstants; import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration; import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap; import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants; @@ -542,14 +541,14 @@ public class ReceiveAuthnResponseTaskTest { assertTrue("eidProcess flag", session.isEidProcess()); assertFalse("useMandate flag", session.isMandateUsed()); - checkAttributeInSession(session,PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max"); - checkAttributeInSession(session,PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann"); - checkAttributeInSession(session,PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); - checkAttributeInSession(session,PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/high"); - checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT"); + checkAttributeInSession(session, PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max"); + checkAttributeInSession(session, PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann"); + checkAttributeInSession(session, PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); + checkAttributeInSession(session, PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, "http://eidas.europa.eu/LoA/high"); + checkAttributeInSession(session, PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT"); //pre-generated eIDAS identifer - checkAttributeInSession(session, MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcM4UcyhDTNGYmVdrIoY="); + checkAttributeInSession(session, PvpAttributeDefinitions.BPK_NAME, "AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY="); } @@ -587,7 +586,7 @@ public class ReceiveAuthnResponseTaskTest { checkAttributeInSession(session,PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT"); - checkAttributeInSession(session,MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcM4UcyhDTNGYmVdrIoY="); + checkAttributeInSession(session,PvpAttributeDefinitions.BPK_NAME, "AT+CC:QVGm48cqcM4UcyhDTNGYmVdrIoY="); } @@ -625,7 +624,7 @@ public class ReceiveAuthnResponseTaskTest { checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT"); //pre-generated eIDAS identifer - checkAttributeInSession(session,MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY="); + checkAttributeInSession(session,PvpAttributeDefinitions.BPK_NAME, "QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY="); } @@ -663,7 +662,7 @@ public class ReceiveAuthnResponseTaskTest { checkAttributeInSession(session,PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, "AT"); //pre-generated eIDAS identifer - checkAttributeInSession(session,MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY="); + checkAttributeInSession(session,PvpAttributeDefinitions.BPK_NAME, "AT+AB:QVGm48cqcasfasfsafsafdM4UcyhDTNGYmVdrIoY="); } @@ -708,7 +707,7 @@ public class ReceiveAuthnResponseTaskTest { checkAttributeInSession(session, PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, "urn:publicid:gv.at:baseid+XERSB"); //pre-generated eIDAS identifer - checkAttributeInSession(session, MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, "QVGm48cqcM4UcyhDTNGYmVdrIoY="); + checkAttributeInSession(session, PvpAttributeDefinitions.BPK_NAME, "AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY="); assertNull("find nat. person bpk for mandator", session.getGenericDataFromSession( PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, String.class)); @@ -758,8 +757,7 @@ public class ReceiveAuthnResponseTaskTest { //pre-generated eIDAS identifer - checkAttributeInSession(session, MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, - "QVGm48cqcM4UcyhDTNGYmVdrIoY="); + checkAttributeInSession(session, PvpAttributeDefinitions.BPK_NAME, "AT+XX:QVGm48cqcM4UcyhDTNGYmVdrIoY="); } diff --git a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java index f6ffc729..1feb684d 100644 --- a/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java +++ b/modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java @@ -18,6 +18,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.internal.util.collections.Sets; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.core.xml.schema.XSString; import org.opensaml.core.xml.util.XMLObjectSupport; @@ -41,6 +42,7 @@ import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePe import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes; +import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; 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; @@ -213,7 +215,7 @@ public class RequestIdAustriaSystemTaskTest { //validate state final EaafRequestedAttributes reqAttr = validate(); - Assert.assertEquals("#Req Attribute", 4, reqAttr.getAttributes().size()); + Assert.assertEquals("#Req Attribute", 5, reqAttr.getAttributes().size()); Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.eidas.uniqueId", reqAttr.getAttributes().get(0).getName()); @@ -246,15 +248,15 @@ public class RequestIdAustriaSystemTaskTest { ((XSString)reqAttr.getAttributes().get(2).getAttributeValues().get(0)).getValue()); Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderMandateType", - reqAttr.getAttributes().get(3).getName()); - Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(3).getAttributeValues()); + reqAttr.getAttributes().get(4).getName()); + Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(4).getAttributeValues()); Assert.assertEquals("#Req. Attr value", 1, - reqAttr.getAttributes().get(3).getAttributeValues().size()); + reqAttr.getAttributes().get(4).getAttributeValues().size()); org.springframework.util.Assert.isInstanceOf(XSString.class, - reqAttr.getAttributes().get(3).getAttributeValues().get(0), "Wrong requested Attributes Value type"); + reqAttr.getAttributes().get(4).getAttributeValues().get(0), "Wrong requested Attributes Value type"); Assert.assertEquals("Req. Attr. Value", pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).getMandateMode().getMode(), - ((XSString)reqAttr.getAttributes().get(3).getAttributeValues().get(0)).getValue()); + ((XSString)reqAttr.getAttributes().get(4).getAttributeValues().get(0)).getValue()); } @@ -275,33 +277,55 @@ public class RequestIdAustriaSystemTaskTest { LightRequest eidasReq = eidasRequestBuilder.build(); pendingReq.setEidasRequest(eidasReq); + oaParam.setRequestedAttributes(Sets.newSet( + "aabbccdd", + RandomStringUtils.randomAlphanumeric(10), + PvpAttributeDefinitions.BIRTHDATE_NAME)); + //execute test task.execute(pendingReq, executionContext); //validate state final EaafRequestedAttributes reqAttr = validate(); - Assert.assertEquals("#Req Attribute", 6, reqAttr.getAttributes().size()); + Assert.assertEquals("#Req Attribute", 7, reqAttr.getAttributes().size()); - Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderFriendlyName", + + Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.RequiredAttributes", reqAttr.getAttributes().get(3).getName()); - Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues()); + Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(3).getAttributeValues()); Assert.assertEquals("#Req. Attr value", 1, reqAttr.getAttributes().get(3).getAttributeValues().size()); org.springframework.util.Assert.isInstanceOf(XSString.class, reqAttr.getAttributes().get(3).getAttributeValues().get(0), "Wrong requested Attributes Value type"); - Assert.assertEquals("Req. Attr. Value", eidasReq.getProviderName(), + + List reqProfiles = KeyValueUtils.getListOfCsvValues( ((XSString)reqAttr.getAttributes().get(3).getAttributeValues().get(0)).getValue()); + reqProfiles.stream().forEach( + el -> assertTrue("missing IDA attribute: " + el, oaParam.getRequestedAttributes().contains(el))); - Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderUniqueId", + + Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderFriendlyName", reqAttr.getAttributes().get(4).getName()); - Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues()); + Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(4).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(), + Assert.assertEquals("Req. Attr. Value", eidasReq.getProviderName(), ((XSString)reqAttr.getAttributes().get(4).getAttributeValues().get(0)).getValue()); + Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderUniqueId", + reqAttr.getAttributes().get(5).getName()); + Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(5).getAttributeValues()); + Assert.assertEquals("#Req. Attr value", 1, + reqAttr.getAttributes().get(5).getAttributeValues().size()); + org.springframework.util.Assert.isInstanceOf(XSString.class, + reqAttr.getAttributes().get(5).getAttributeValues().get(0), "Wrong requested Attributes Value type"); + Assert.assertEquals("Req. Attr. Value", eidasReq.getRequesterId(), + ((XSString)reqAttr.getAttributes().get(5).getAttributeValues().get(0)).getValue()); + + + } @Test @@ -330,31 +354,31 @@ public class RequestIdAustriaSystemTaskTest { //validate state final EaafRequestedAttributes reqAttr = validate(); - Assert.assertEquals("#Req Attribute", 7, reqAttr.getAttributes().size()); + Assert.assertEquals("#Req Attribute", 8, reqAttr.getAttributes().size()); Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderMandateProfiles", - reqAttr.getAttributes().get(5).getName()); - Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(1).getAttributeValues()); + reqAttr.getAttributes().get(6).getName()); + Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(6).getAttributeValues()); Assert.assertEquals("#Req. Attr value", 1, - reqAttr.getAttributes().get(5).getAttributeValues().size()); + reqAttr.getAttributes().get(6).getAttributeValues().size()); org.springframework.util.Assert.isInstanceOf(XSString.class, - reqAttr.getAttributes().get(5).getAttributeValues().get(0), "Wrong requested Attributes Value type"); + reqAttr.getAttributes().get(6).getAttributeValues().get(0), "Wrong requested Attributes Value type"); List reqProfiles = KeyValueUtils.getListOfCsvValues( - ((XSString)reqAttr.getAttributes().get(5).getAttributeValues().get(0)).getValue()); + ((XSString)reqAttr.getAttributes().get(6).getAttributeValues().get(0)).getValue()); reqProfiles.stream().forEach(el -> assertTrue("missing profile: " + el, mandateProfiles.contains(el))); Assert.assertEquals("Wrong req attr.", "urn:eidgvat:attributes.ServiceProviderMandateType", - reqAttr.getAttributes().get(6).getName()); - Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(6).getAttributeValues()); + reqAttr.getAttributes().get(7).getName()); + Assert.assertNotNull("Req. Attr value element", reqAttr.getAttributes().get(7).getAttributeValues()); Assert.assertEquals("#Req. Attr value", 1, - reqAttr.getAttributes().get(6).getAttributeValues().size()); + reqAttr.getAttributes().get(7).getAttributeValues().size()); org.springframework.util.Assert.isInstanceOf(XSString.class, - reqAttr.getAttributes().get(6).getAttributeValues().get(0), "Wrong requested Attributes Value type"); + reqAttr.getAttributes().get(7).getAttributeValues().get(0), "Wrong requested Attributes Value type"); Assert.assertEquals("Req. Attr. Value", SpMandateModes.LEGAL_FORCE.getMode(), - ((XSString)reqAttr.getAttributes().get(6).getAttributeValues().get(0)).getValue()); + ((XSString)reqAttr.getAttributes().get(7).getAttributeValues().get(0)).getValue()); } diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java index be5d7c7d..8da7ddd0 100644 --- a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java +++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/MsEidasNodeConstants.java @@ -31,7 +31,6 @@ import java.util.List; import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; import at.gv.egiz.eaaf.core.impl.data.Triple; -import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder; public class MsEidasNodeConstants { // ************ configuration properties ************ @@ -189,17 +188,7 @@ public class MsEidasNodeConstants { public static final String EID_BINDING_PUBLIC_KEY_NAME = "urn:eidgvat:attributes.binding.pubkey"; - - - // ---- Attribute configuration ------ - public static final String ATTR_EIDAS_PERSONAL_IDENTIFIER = - AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER + PvpAttributeDefinitions.BPK_NAME; - public static final String ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER = - AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME; - public static final String ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER = - AbstractAuthenticationDataBuilder.GENERIC_AUTHDATA_IDENTIFIER - + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME; - + public static final String AUTH_DATA_SZR_AUTHBLOCK = "authData_AUTHBLOCK"; public static final String AUTH_DATA_EIDAS_BIND = "authData_EIDAS_BIND"; diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java index e719735c..673b8ef5 100644 --- a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java +++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java @@ -24,73 +24,92 @@ package at.asitplus.eidas.specific.core.builder; import java.time.Instant; - -import org.springframework.stereotype.Service; +import java.util.Optional; +import java.util.Set; import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.data.IAuthProcessDataContainer; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.data.Triple; import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData; import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder; import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper; import lombok.extern.slf4j.Slf4j; -@Service("AuthenticationDataBuilder") @Slf4j public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder { + private static final String ERROR_B11 = "builder.11"; + @Override - protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException { + protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException { final EidAuthProcessDataWrapper authProcessData = - pendingReq.getSessionData(EidAuthProcessDataWrapper.class); - EidAuthenticationData authData = new EidAuthenticationData(); - - //set basis infos + pendingReq.getSessionData(EidAuthProcessDataWrapper.class); + final EidAuthenticationData authData = new EidAuthenticationData(); + + // set basis infos super.generateDeprecatedBasicAuthData(authData, pendingReq, authProcessData); - + // set specific informations authData.setSsoSessionValidTo( Instant.now().plusSeconds(MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60)); - authData.setEidStatus(authProcessData.isTestIdentity() - ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY); - + authData.setEidStatus(authProcessData.isTestIdentity() + ? EidIdentityStatusLevelValues.TESTIDENTITY + : EidIdentityStatusLevelValues.IDENTITY); + return authData; } @Override - protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq) + protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq) throws EaafException { if (authData instanceof EidAuthenticationData) { - ((EidAuthenticationData)authData).setGenericData( - ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, + ((EidAuthenticationData) authData).setGenericData( + ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, pendingReq.getUniquePiiTransactionIdentifier()); log.trace("Inject piiTransactionId: {} into AuthData", pendingReq.getUniquePiiTransactionIdentifier()); - + // set specific informations - ((EidAuthenticationData)authData).setSsoSessionValidTo( + ((EidAuthenticationData) authData).setSsoSessionValidTo( Instant.now().plusSeconds(MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60)); - //set E-ID status-level + // set E-ID status-level final EidAuthProcessDataWrapper authProcessData = - pendingReq.getSessionData(EidAuthProcessDataWrapper.class); - ((EidAuthenticationData)authData).setEidStatus(authProcessData.isTestIdentity() - ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY); - + pendingReq.getSessionData(EidAuthProcessDataWrapper.class); + ((EidAuthenticationData) authData).setEidStatus(authProcessData.isTestIdentity() + ? EidIdentityStatusLevelValues.TESTIDENTITY + : EidIdentityStatusLevelValues.IDENTITY); + + // forward all requested IDA attributes into authData + forwardAllRequestedIdaAttributes(authProcessData, (EidAuthenticationData) authData, + pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class) + .getRequestedAttributes()); + + // build specific bPK attribute + buildNatPersonInfos((EidAuthenticationData) authData, authProcessData); + + // handle mandate informations + buildMandateInformation((EidAuthenticationData) authData, pendingReq, authProcessData); + } else { - throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: " + throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: " + authData.getClass().getName()); - + } - + } @Override @@ -119,4 +138,120 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder } + protected String customizeLegalPersonSourcePin(String sourcePin, String sourcePinType) { + log.trace("Use legal-person sourcePin as it is"); + return sourcePin; + + } + + protected String customizeBpkAttribute(String pvpBpkAttrValue) { + log.trace("Use natural-person bPK as it is"); + return pvpBpkAttrValue; + + } + + private void forwardAllRequestedIdaAttributes(EidAuthProcessDataWrapper authProcessData, + EidAuthenticationData authData, Set requestedIdaAttributes) { + if (requestedIdaAttributes != null && !requestedIdaAttributes.isEmpty()) { + log.trace("Forwarding IDA requested attributes ... "); + authProcessData.getGenericSessionDataStream() + .filter(el -> requestedIdaAttributes.contains(el.getKey())) + .forEach(el -> { + try { + authData.setGenericData(el.getKey(), el.getValue()); + + } catch (final EaafStorageException e) { + log.error("Can not store attribute: {} into session.", el.getKey(), e); + throw new RuntimeException(e); + + } + }); + } else { + log.trace("No IDA requested attributes to forwarding. Nothing todo"); + + } + } + + private void buildMandateInformation(EidAuthenticationData authData, IRequest pendingReq, + EidAuthProcessDataWrapper authProcessData) throws EaafAuthenticationException, EaafBuilderException, + EaafStorageException { + authData.setUseMandate(authProcessData.isMandateUsed()); + if (authProcessData.isMandateUsed()) { + log.debug("Build mandate-releated authentication data ... "); + if (authProcessData.isForeigner()) { + buildMandateInformationForEidasIncoming(); + + } else { + buildMandateInformationForEidasOutgoing(authData, pendingReq, authProcessData); + + } + } + } + + private void buildMandateInformationForEidasIncoming() { + log.debug("Find eIDAS incoming process. Generated mandate-information for ID-Austria system ... "); + + // TODO: implement IDA specific processing of foreign mandate + + } + + private void buildNatPersonInfos(EidAuthenticationData authData, + EidAuthProcessDataWrapper authProcessData) throws EaafStorageException { + // clean-up BPK attribute and forward it as new property + authData.setGenericData(PvpAttributeDefinitions.BPK_NAME, + customizeBpkAttribute(authProcessData.getGenericDataFromSession( + PvpAttributeDefinitions.BPK_NAME, String.class))); + + } + + private void buildMandateInformationForEidasOutgoing(EidAuthenticationData authData, IRequest pendingReq, + EidAuthProcessDataWrapper authProcessData) throws EaafAuthenticationException, EaafBuilderException, + EaafStorageException { + log.debug("Find eIDAS outgoing process. Generated mandate-information for other country ... "); + if (authProcessData.getGenericDataFromSession( + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME) != null) { + final Optional> missingAttribute = + MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_NAT_PVP_ATTRIBUTES.stream() + .filter(el -> authProcessData.getGenericDataFromSession(el.getFirst()) == null) + .findFirst(); + if (missingAttribute.isPresent()) { + log.error("ID-Austria response contains not all attributes for nat. person mandator. Missing: {}", + missingAttribute.get().getFirst()); + throw new EaafAuthenticationException(ERROR_B11, new Object[] { "Nat. person mandate" }); + + } else { + log.trace("Find nat. person mandate. Mandate can be used as it is "); + authData.setGenericData(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, + customizeBpkAttribute(authProcessData.getGenericDataFromSession( + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, String.class))); + + } + + } else { + final Optional> missingAttribute = + MsEidasNodeConstants.DEFAULT_REQUIRED_MANDATE_JUR_PVP_ATTRIBUTES.stream() + .filter(el -> authProcessData.getGenericDataFromSession(el.getFirst()) == null) + .findFirst(); + if (missingAttribute.isPresent()) { + log.error("ID-Austria response contains not all attributes for legal. person mandator. Missing: {}", + missingAttribute.get().getFirst()); + throw new EaafAuthenticationException(ERROR_B11, new Object[] { "Legal. person mandate" }); + + } else { + log.trace( + "Find jur. person mandate. Generate eIDAS identifier from legal-person sourcePin and type ... "); + final String sourcePin = authProcessData.getGenericDataFromSession( + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, String.class); + final String sourcePinType = authProcessData.getGenericDataFromSession( + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, String.class); + + // customize attribute-value for source-pin + final String sourcePinToUse = customizeLegalPersonSourcePin(sourcePin, sourcePinType); + log.debug("Use legal-person eIDAS identifer: {} from baseId: {} and baseIdType: {}", + sourcePinToUse, sourcePin, sourcePinType); + authData.setGenericData(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinToUse); + + } + } + } } diff --git a/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml b/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml index ee67d712..af3594a5 100644 --- a/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml +++ b/modules/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml @@ -23,9 +23,6 @@ - - diff --git a/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java index 12936a59..8b2eebd4 100644 --- a/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java +++ b/modules/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java @@ -1,6 +1,9 @@ package at.asitplus.eidas.specific.core.test.utils; import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.security.PublicKey; @@ -30,8 +33,11 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.w3c.dom.Element; +import com.google.common.collect.Sets; + import at.asitplus.eidas.specific.core.MsEidasNodeConstants; import at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder; +import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration; 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; @@ -49,9 +55,9 @@ import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser; -import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration; import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import lombok.SneakyThrows; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; @RunWith(SpringJUnit4ClassRunner.class) @@ -71,7 +77,8 @@ public class AuthenticationDataBuilderTest { private MockHttpServletResponse httpResp; private TestRequestImpl pendingReq; - private DummySpConfiguration oaParam; + private Map spConfig; + private ServiceProviderConfiguration oaParam; private String eidasBind; private String authBlock; @@ -86,18 +93,20 @@ public class AuthenticationDataBuilderTest { } @Before + @SneakyThrows public void initialize() throws EaafStorageException { httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); httpResp = new MockHttpServletResponse(); 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"); - oaParam = new DummySpConfiguration(spConfig, basicConfig); - + oaParam = new ServiceProviderConfiguration(spConfig, basicConfig); + oaParam.setBpkTargetIdentifier("urn:publicid:gv.at:cdid+XX"); + pendingReq = new TestRequestImpl(); pendingReq.setAuthUrl("https://localhost/ms_connector"); pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); @@ -119,6 +128,260 @@ public class AuthenticationDataBuilderTest { } + @Test + public void eidasProxyModeWithJurMandate() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String commonMandate = RandomStringUtils.randomAlphabetic(10); + + // set constant country-code and sourcePin to check hashed eIDAS identifier + String sourcePinMandate = "asfdsadfsadfsafsdafsadfasr"; + spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EE"); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, commonMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, + EaafConstants.URN_PREFIX_BASEID + "+XFN"); + + oaParam.setRequestedAttributes(Sets.newHashSet( + PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME)); + + // execute test + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + + // validate state + Assert.assertNotNull("AuthData null", authData); + assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate()); + + //check mandate informations + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, commonMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinMandate); + + } + + @Test + public void eidasProxyModeWithJurMandateMissingAttribute() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + // set constant country-code and sourcePin to check hashed eIDAS identifier + String sourcePinMandate = "asfdsadfsadfsafsdafsadfasr"; + spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EE"); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, + EaafConstants.URN_PREFIX_BASEID + "+XFN"); + + // execute test + // execute test + EaafAuthenticationException error = assertThrows(EaafAuthenticationException.class, + () -> authenticationDataBuilder.buildAuthenticationData(pendingReq)); + Assert.assertEquals("wrong errorId", "builder.11", error.getErrorId()); + + } + + @Test + public void eidasProxyModeWithNatMandate() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String givenNameMandate = RandomStringUtils.randomAlphabetic(10); + String familyNameMandate = RandomStringUtils.randomAlphabetic(10); + String dateOfBirthMandate = "1957-09-15"; + String bpkMandate = RandomStringUtils.randomAlphanumeric(10); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, "AT+XX:" + bpkMandate); + + oaParam.setRequestedAttributes(Sets.newHashSet( + PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME)); + + // execute test + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + + // validate state + Assert.assertNotNull("AuthData null", authData); + assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate()); + + //check mandate informations + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "1957-09-15"); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, "AT+XX:" + bpkMandate); + + } + + @Test + public void eidasProxyModeWithNatMandateWrongBpkFormat() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String givenNameMandate = RandomStringUtils.randomAlphabetic(10); + String familyNameMandate = RandomStringUtils.randomAlphabetic(10); + String dateOfBirthMandate = "1957-09-15"; + String bpkMandate = RandomStringUtils.randomAlphanumeric(10); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate); + + oaParam.setRequestedAttributes(Sets.newHashSet( + PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME)); + + // execute test + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + + // validate state + Assert.assertNotNull("AuthData null", authData); + assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate()); + + //check mandate informations + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "1957-09-15"); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate); + + } + + @Test + public void eidasProxyModeWithNatMandateMissingAttribute() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String familyNameMandate = RandomStringUtils.randomAlphabetic(10); + String dateOfBirthMandate = "1957-09-15"; + String bpkMandate = RandomStringUtils.randomAlphanumeric(10); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate); + + // execute test + EaafAuthenticationException error = assertThrows(EaafAuthenticationException.class, + () -> authenticationDataBuilder.buildAuthenticationData(pendingReq)); + Assert.assertEquals("wrong errorId", "builder.11", error.getErrorId()); + + } + + + + @Test + @SneakyThrows + public void eidasProxyMode() throws EaafAuthenticationException { + // initialize state + pendingReq = new TestRequestImpl(); + pendingReq.setAuthUrl("https://localhost/ms_connector"); + pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); + pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10)); + pendingReq.setSpConfig(oaParam); + boolean isTestIdentity = RandomUtils.nextBoolean(); + + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setForeigner(false); + + String bpk = RandomStringUtils.randomAlphanumeric(10); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.BPK_NAME, "eidas+AT+XX:" + bpk); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + "http://eidas.europa.eu/LoA/high"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, + RandomStringUtils.randomAlphabetic(2)); + + String randAttr = RandomStringUtils.randomAlphabetic(10); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + randAttr, RandomStringUtils.randomAlphabetic(10)); + + oaParam.setRequestedAttributes(Sets.newHashSet(randAttr, + PvpAttributeDefinitions.BPK_NAME, + PvpAttributeDefinitions.GIVEN_NAME_NAME, + PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, + PvpAttributeDefinitions.BIRTHDATE_NAME, + PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + PvpAttributeDefinitions.EID_ISSUING_NATION_NAME)); + + + // execute + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + // validate state + Assert.assertNotNull("AuthData null", authData); + Assert.assertNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class)); + Assert.assertNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class)); + Assert.assertNotNull("LoA null", authData.getEidasQaaLevel()); + + Assert.assertEquals("FamilyName", "Mustermann", authData.getFamilyName()); + Assert.assertEquals("GivenName", "Max", authData.getGivenName()); + Assert.assertEquals("DateOfBirth", "1940-01-01", authData.getDateOfBirth()); + + Assert.assertEquals("LoA", "http://eidas.europa.eu/LoA/high", authData.getEidasQaaLevel()); + Assert.assertEquals("EID-ISSUING-NATION", + pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession( + PvpAttributeDefinitions.EID_ISSUING_NATION_NAME), + authData.getCiticenCountryCode()); + + checkGenericAttribute(authData, PvpAttributeDefinitions.BPK_NAME, "eidas+AT+XX:" + bpk); + checkGenericAttribute(authData, PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max"); + checkGenericAttribute(authData, PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann"); + checkGenericAttribute(authData, PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); + + Assert.assertEquals("random optional attr.", + pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession( + randAttr), + authData.getGenericData(randAttr, String.class)); + + } + + + @Test public void eidMode() throws EaafAuthenticationException { // initialize state @@ -207,10 +470,48 @@ public class AuthenticationDataBuilderTest { authData.getBpk()); Assert.assertEquals("bPKType", EaafConstants.URN_PREFIX_CDID + "XX", authData.getBpkType()); Assert.assertNotNull("IDL", authData.getIdentityLink()); + + } + + private void injectRepresentativeInfosIntoSession() throws EaafStorageException { + boolean isTestIdentity = RandomUtils.nextBoolean(); + pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + String givenName = RandomStringUtils.randomAlphabetic(10); + String familyName = RandomStringUtils.randomAlphabetic(10); + String dateOfBirth = "1956-12-08"; + String bpk = RandomStringUtils.randomAlphanumeric(10); + String cc = pendingReq.getSessionData(AuthProcessDataWrapper.class) + .getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class); + String spC = RandomStringUtils.randomAlphabetic(2).toUpperCase(); + spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + cc + "+" + spC); + + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setForeigner(false); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.GIVEN_NAME_NAME, givenName); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, familyName); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.BIRTHDATE_NAME, dateOfBirth); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, bpk); + + //set LoA level attribute instead of explicit session-data + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel()); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setQaaLevel(null); } + + private void checkGenericAttribute(IAuthData authData, String attrName, String expected) { + assertEquals("Wrong: " + attrName, expected, authData.getGenericData(attrName, String.class)); + + } + private IIdentityLink buildDummyIdl() { return new IIdentityLink() { diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java index 86ca49fa..f66bb799 100644 --- a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java +++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java @@ -15,6 +15,7 @@ import lombok.Data; @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "mds", + "autoIncludeWithMandates", "mandator" }) @Data @@ -27,6 +28,12 @@ public class Type { @JsonProperty("mds") private Boolean mds; + /** + * true if that attribute has to be included into eIDAS response in case of mandates. + */ + @JsonProperty("autoIncludeWithMandates") + private Boolean autoIncludeWithMandates; + /** * Classifie that attribute to specific mandate modes. */ diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java index 92165412..bf1c5e5f 100644 --- a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java +++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java @@ -1,6 +1,7 @@ package at.asitplus.eidas.specific.modules.msproxyservice.protocol; import java.io.IOException; +import java.util.Optional; import java.util.UUID; import javax.annotation.PostConstruct; @@ -15,12 +16,11 @@ import org.springframework.context.ApplicationContext; import org.springframework.core.io.ResourceLoader; import org.springframework.web.util.UriComponentsBuilder; -import at.asitplus.eidas.specific.core.MsEidasNodeConstants; import at.asitplus.eidas.specific.core.gui.StaticGuiBuilderConfiguration; import at.asitplus.eidas.specific.modules.core.eidas.EidasConstants; -import at.asitplus.eidas.specific.modules.core.eidas.service.EidasAttributeRegistry; import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants; import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException; +import at.asitplus.eidas.specific.modules.msproxyservice.service.ProxyEidasAttributeRegistry; import at.asitplus.eidas.specific.modules.msproxyservice.utils.EidasProxyServiceUtils; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; @@ -69,35 +69,35 @@ public class ProxyServiceAuthenticationAction implements IAction { @Autowired ISpringMvcGuiFormBuilder guiBuilder; @Autowired - EidasAttributeRegistry attrRegistry; + ProxyEidasAttributeRegistry 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(); + try { + final ILightRequest eidasReq = ((ProxyServicePendingRequest) pendingReq).getEidasRequest(); + + // build eIDAS response + final Builder lightRespBuilder = LightResponse.builder(); lightRespBuilder.id(UUID.randomUUID().toString()); lightRespBuilder.inResponseToId(eidasReq.getId()); lightRespBuilder.relayState(eidasReq.getRelayState()); - + lightRespBuilder.status(ResponseStatus.builder() .statusCode(EidasConstants.SUCCESS_URI) .build()); - - //TODO: check if we can use transient subjectNameIds + + // TODO: check if we can use transient subjectNameIds lightRespBuilder.subject(UUID.randomUUID().toString()); lightRespBuilder.subjectNameIdFormat(NameIDType.TRANSIENT); - - //TODO: + + // TODO: lightRespBuilder.issuer(basicConfig.getBasicConfiguration( MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID)); - lightRespBuilder.levelOfAssurance(authData.getEidasQaaLevel()); + lightRespBuilder.levelOfAssurance(authData.getEidasQaaLevel()); lightRespBuilder.attributes(buildAttributesFromAuthData(authData, eidasReq)); - + // set SLO response object of EAAF framework final SloInformationImpl sloInformation = new SloInformationImpl(); sloInformation.setProtocolType(pendingReq.requestedModule()); @@ -121,7 +121,7 @@ public class ProxyServiceAuthenticationAction implements IAction { } } - + @Override public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { return true; @@ -133,28 +133,29 @@ public class ProxyServiceAuthenticationAction implements IAction { return PROXYSERVICE_AUTH_ACTION_NAME; } - /** * Forward eIDAS Light response to eIDAS node. - * - * @param pendingReq Current pending request. - * @param httpReq Current HTTP request - * @param httpResp Current HTTP response + * + * @param pendingReq Current pending request. + * @param httpReq Current HTTP request + * @param httpResp Current HTTP response * @param lightResponse eIDAS LightResponse * @throws EaafConfigurationException In case of a configuration error - * @throws IOException In case of a general error - * @throws GuiBuildException In case of a GUI rendering error, if http POST binding is used - * @throws ServletException In case of a general error + * @throws IOException In case of a general error + * @throws GuiBuildException In case of a GUI rendering error, if http + * POST binding is used + * @throws ServletException In case of a general error */ public void forwardToEidasProxy(IRequest pendingReq, HttpServletRequest httpReq, - HttpServletResponse httpResp, LightResponse lightResponse) throws EaafConfigurationException, IOException, + HttpServletResponse httpResp, LightResponse lightResponse) throws EaafConfigurationException, + IOException, GuiBuildException, ServletException { // put request into shared cache final BinaryLightToken token = putResponseInCommunicationCache(lightResponse); final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token); - + // select forward URL regarding the selected environment final String forwardUrl = basicConfig.getBasicConfiguration( MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL); @@ -196,148 +197,80 @@ public class ProxyServiceAuthenticationAction implements IAction { } } - - @PostConstruct + + @PostConstruct private void checkConfiguration() { - //TODO: validate configuration on start-up - + // TODO: validate configuration on start-up + } - - - private ImmutableAttributeMap buildAttributesFromAuthData(IAuthData authData, + + private ImmutableAttributeMap buildAttributesFromAuthData(IAuthData authData, ILightRequest eidasReq) { - IEidAuthData eidAuthData = (IEidAuthData) authData; + final IEidAuthData eidAuthData = (IEidAuthData) authData; + final ImmutableAttributeMap.Builder attributeMap = ImmutableAttributeMap.builder(); + + // inject all requested attributres + injectRequestedAttributes(attributeMap, eidasReq, eidAuthData); + if (eidAuthData.isUseMandate()) { log.debug("Building eIDAS Proxy-Service response with mandate ... "); - final ImmutableAttributeMap.Builder attributeMap = ImmutableAttributeMap.builder(); - injectRepesentativeInformation(attributeMap, eidAuthData); - injectMandatorInformation(attributeMap, eidAuthData); - - // work-around that injects nat. person subject to bypass validation on eIDAS Node + injectMdsRepesentativeInformation(attributeMap, eidAuthData, eidasReq.getRequestedAttributes()); + + // work-around that injects nat. person subject to bypass validation on eIDAS + // Node injectJurPersonWorkaroundIfRequired(attributeMap, eidasReq, authData); - - return attributeMap.build(); - - } else { - log.debug("Building eIDAS Proxy-Service response without mandates ... "); - return buildAttributesWithoutMandate(eidAuthData); - - } - } - - private void injectMandatorInformation( - ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData) { - String natMandatorId = eidAuthData.getGenericData( - MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, String.class); - - if (StringUtils.isNotEmpty(natMandatorId)) { - log.debug("Injecting natural mandator informations ... "); - final AttributeDefinition attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); - final AttributeDefinition attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); - final AttributeDefinition attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first(); - final AttributeDefinition attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first(); - - attributeMap.put(attrDefPersonalId, natMandatorId); - attributeMap.put(attrDefFamilyName, eidAuthData.getGenericData( - PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, String.class)); - attributeMap.put(attrDefGivenName, eidAuthData.getGenericData( - PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, String.class)); - attributeMap.put(attrDefDateOfBirth, eidAuthData.getGenericData( - PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, String.class)); - - } else { - log.debug("Injecting legal mandator informations ... "); - final AttributeDefinition commonName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_LEGALNAME).first(); - final AttributeDefinition legalPersonId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first(); - - attributeMap.put(commonName, eidAuthData.getGenericData( - PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, String.class)); - attributeMap.put(legalPersonId, eidAuthData.getGenericData( - MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, String.class)); - - } - } - private void injectRepesentativeInformation( - ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData) { - final AttributeDefinition attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER).first(); - final AttributeDefinition attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME).first(); - final AttributeDefinition attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME).first(); - final AttributeDefinition attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH).first(); - - attributeMap.put(attrDefPersonalId, - eidAuthData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class)); - attributeMap.put(attrDefFamilyName, eidAuthData.getFamilyName()); - attributeMap.put(attrDefGivenName, eidAuthData.getGivenName()); - - //TODO: throw an error in case of SZR Date with month or day = "00" - attributeMap.put(attrDefDateOfBirth, eidAuthData.getDateOfBirth()); - + } + + return attributeMap.build(); + } - /** - * Work-around to inject representative information as nat. person subject to bypass eIDAS Node validation. - * - *

Injection will only be done if this work-around is enabled by configuration, - * the mandator is a legal person, and both legal and natural person subject's is requested.

- * - * @param attributeMap Attribute set for eIDAS response - * @param eidasReq Incoming eIDAS request - * @param authData Authentication data - */ - private void injectJurPersonWorkaroundIfRequired( - ImmutableAttributeMap.Builder attributeMap, ILightRequest eidasReq, IAuthData authData) { - if (isLegalPersonWorkaroundActive() && isLegalPersonMandateAvailable(authData) - && EidasProxyServiceUtils.isNaturalPersonRequested(eidasReq) - && EidasProxyServiceUtils.isLegalPersonRequested(eidasReq)) { - log.debug("Injecting representative information as nat. person subject to bypass eIDAS Node validation"); - attributeMap.putAll(buildAttributesWithoutMandate(authData)); - - } + private void injectRequestedAttributes(ImmutableAttributeMap.Builder attributeMap, ILightRequest eidasReq, + IEidAuthData eidAuthData) { + eidasReq.getRequestedAttributes().getAttributeMap().keySet().stream() + .forEach(el -> injectEidasAttribute(attributeMap, eidAuthData, + el.getNameUri().toString(), eidAuthData.isUseMandate())); + } - - private ImmutableAttributeMap buildAttributesWithoutMandate(IAuthData eidAuthData) { - //TODO: throw an error in case of SZR Date with month or day = "00" - return buildAttributesWithoutMandate( - eidAuthData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class), - eidAuthData.getFamilyName(), - eidAuthData.getGivenName(), - eidAuthData.getDateOfBirth()); - + + private void injectMdsRepesentativeInformation( + ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData, + ImmutableAttributeMap requestedAttributes) { + attrRegistry.getRepresentativeAttributesToAddByDefault() + .filter(el -> requestedAttributes.getAttributeValuesByNameUri(el) == null) + .forEach(el -> injectEidasAttribute(attributeMap, eidAuthData, el, true)); + } - private ImmutableAttributeMap buildAttributesWithoutMandate(String personalIdentifier, String familyName, - String givenName, String dateOfBirth) { - final AttributeDefinition attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); - final AttributeDefinition attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); - final AttributeDefinition attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first(); - final AttributeDefinition attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first(); - - final ImmutableAttributeMap.Builder attributeMap = - ImmutableAttributeMap.builder() - .put(attrDefPersonalId, personalIdentifier) - .put(attrDefFamilyName, familyName) - .put(attrDefGivenName, givenName) - .put(attrDefDateOfBirth, dateOfBirth); - - return attributeMap.build(); - + private void injectEidasAttribute(ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData, + String eidasAttrName, boolean mandatesUsed) { + final Optional releatedIdaAttribute = + attrRegistry.mapEidasAttributeToSpecificIdaAttribute(eidasAttrName, mandatesUsed); + if (releatedIdaAttribute.isPresent()) { + log.trace("Mapping IDA attribute: {} to eIDAS attribute: {}", releatedIdaAttribute.get(), + eidasAttrName); + final String idaAttrValue = eidAuthData.getGenericData(releatedIdaAttribute.get(), String.class); + if (StringUtils.isNotEmpty(idaAttrValue)) { + log.debug("Build eIDAS attribute: {} from IDA attribute: {}", eidasAttrName, releatedIdaAttribute + .get()); + attributeMap.put( + attrRegistry.getCoreRegistry().getCoreAttributeRegistry().getByName(eidasAttrName), + idaAttrValue); + + } else { + log.info("No IDA attribute: {}, eIDAS attribute: {} will be ignored", releatedIdaAttribute.get(), + eidasAttrName); + + } + + } else { + log.warn("Can not build eIDAS attribute: {}, because there is not corresponding IDA attribute defined", + eidasAttrName); + + } } - + private BinaryLightToken putResponseInCommunicationCache(ILightResponse lightResponse) throws ServletException { final BinaryLightToken binaryLightToken; @@ -358,17 +291,61 @@ public class ProxyServiceAuthenticationAction implements IAction { return binaryLightToken; } + /** + * Work-around to inject representative information as nat. person subject to + * bypass eIDAS Node validation. + * + *

+ * Injection will only be done if this work-around is enabled by + * configuration, the mandator is a legal person, and both legal and natural + * person subject's is requested. + *

+ * + * @param attributeMap Attribute set for eIDAS response + * @param eidasReq Incoming eIDAS request + * @param authData Authentication data + */ + private void injectJurPersonWorkaroundIfRequired( + ImmutableAttributeMap.Builder attributeMap, ILightRequest eidasReq, IAuthData authData) { + if (isLegalPersonWorkaroundActive() && isLegalPersonMandateAvailable(authData) + && EidasProxyServiceUtils.isNaturalPersonRequested(eidasReq) + && EidasProxyServiceUtils.isLegalPersonRequested(eidasReq)) { + log.debug( + "Injecting representative information as nat. person subject to bypass eIDAS Node validation"); + + final AttributeDefinition attrDefPersonalId = + attrRegistry.getCoreRegistry().getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); + final AttributeDefinition attrDefFamilyName = + attrRegistry.getCoreRegistry().getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); + final AttributeDefinition attrDefGivenName = + attrRegistry.getCoreRegistry().getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first(); + final AttributeDefinition attrDefDateOfBirth = + attrRegistry.getCoreRegistry().getCoreAttributeRegistry().getByFriendlyName( + EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first(); + + attributeMap.put(attrDefPersonalId, authData.getGenericData(PvpAttributeDefinitions.BPK_NAME, + String.class)); + attributeMap.put(attrDefFamilyName, authData.getFamilyName()); + attributeMap.put(attrDefGivenName, authData.getGivenName()); + attributeMap.put(attrDefDateOfBirth, authData.getDateOfBirth()); + + } + } + private boolean isLegalPersonWorkaroundActive() { return basicConfig.getBasicConfigurationBoolean( - MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_WORKAROUND_MANDATES_LEGAL_PERSON, + MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_WORKAROUND_MANDATES_LEGAL_PERSON, false); - + } - + private boolean isLegalPersonMandateAvailable(IAuthData authData) { return StringUtils.isNoneEmpty(authData.getGenericData( - MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, String.class)); - + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, String.class)); + } } diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java index b9e0c488..a6a50100 100644 --- a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java +++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -76,6 +77,19 @@ public class ProxyEidasAttributeRegistry { } + /** + * Get all eIDAS attributes that are added by default in case of mandates. + * + * @return {@link Stream} of eIDAS attributes + */ + @NonNull + public Stream getRepresentativeAttributesToAddByDefault() { + return attributeConfiguration.stream() + .filter(el -> el.getType() != null && el.getType().getAutoIncludeWithMandates()) + .map(el -> el.getEidasAttributeName()); + + } + /** * Get IDA attributes for a specific eIDAS attribute. * @@ -95,8 +109,24 @@ public class ProxyEidasAttributeRegistry { .collect(Collectors.toSet()); } - - + + /** + * Get eIDAS related IDA attribute. + * + * @param eidasAttributeName Name of the eIDAS attribute. + * @param withMandates true if mandates are supported, otherwise false + * @return Name of the related IDA attribute if available + */ + public Optional mapEidasAttributeToSpecificIdaAttribute( + String eidasAttributeName, boolean withMandates) { + return attributeConfiguration.stream() + .filter(el -> el.getEidasAttributeName().equals(eidasAttributeName)) + .findFirst() + .map(el -> withMandates ? el.getIdaAttribute().getWithMandates() : el.getIdaAttribute().getBasic()) + .filter(el -> StringUtils.isNotEmpty(el)); + + } + @PostConstruct private void initialize() throws EaafConfigurationException { final String attrConfPath = basicConfig.getBasicConfiguration( diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/ProxyServiceAuthenticationActionTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/ProxyServiceAuthenticationActionTest.java index c41d6c99..d44ffc2d 100644 --- a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/ProxyServiceAuthenticationActionTest.java +++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/ProxyServiceAuthenticationActionTest.java @@ -12,7 +12,6 @@ import java.net.URISyntaxException; import java.net.URLDecoder; import java.time.Instant; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -35,7 +34,6 @@ import org.springframework.web.context.request.ServletRequestAttributes; import com.google.common.collect.ImmutableSortedSet; -import at.asitplus.eidas.specific.core.MsEidasNodeConstants; import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap; import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummySpConfiguration; import at.asitplus.eidas.specific.modules.core.eidas.EidasConstants; @@ -132,7 +130,7 @@ public class ProxyServiceAuthenticationActionTest { @Test public void missingForwardUrl() { Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.BPK_NAME, "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false); @@ -147,8 +145,7 @@ public class ProxyServiceAuthenticationActionTest { @Test public void responseWithoutMandate() throws EaafException, SpecificCommunicationException { Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, - "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); + attr.put(PvpAttributeDefinitions.BPK_NAME, RandomStringUtils.randomAlphanumeric(10)); IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false); @@ -161,7 +158,7 @@ public class ProxyServiceAuthenticationActionTest { ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); assertEquals("wrong attr. size", 4, respAttr.size()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER, - (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER)); + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_DATEOFBIRTH, @@ -170,12 +167,89 @@ public class ProxyServiceAuthenticationActionTest { } @Test - public void responseWithNatMandate() throws EaafException, SpecificCommunicationException { + public void responseWithoutMandateAndOptionalAttributesExist() throws EaafException, SpecificCommunicationException { + LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest(); + eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder() + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByName("http://eidas.europa.eu/attributes/naturalperson/BirthName")) + .build()); + pendingReq.setEidasRequest(eidasRequestBuilder.build()); + + Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, - "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); + attr.put(PvpAttributeDefinitions.BPK_NAME, + "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); + attr.put("ida_birthname", RandomStringUtils.randomAlphanumeric(10)); + + IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, + RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false); + + //perform test + SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData); + + //validate state + Assert.assertNotNull("Result should be not null", result); + + ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); + assertEquals("wrong attr. size", 5, respAttr.size()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER, + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_DATEOFBIRTH, + authData.getDateOfBirth()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_BIRTHNAME, + (String) attr.get("ida_birthname")); + + } + + @Test + public void responseWithoutMandateAndOptionalAttributesNotExist() throws EaafException, SpecificCommunicationException { + LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest(); + eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder() + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByName("http://eidas.europa.eu/attributes/naturalperson/BirthName")) + .build()); + pendingReq.setEidasRequest(eidasRequestBuilder.build()); + + + Map attr = new HashMap<>(); + attr.put(PvpAttributeDefinitions.BPK_NAME, + "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); + + IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, + RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false); + + //perform test + SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData); + + //validate state + Assert.assertNotNull("Result should be not null", result); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, + ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); + assertEquals("wrong attr. size", 4, respAttr.size()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER, + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_DATEOFBIRTH, + authData.getDateOfBirth()); + + } + + + @Test + public void responseWithNatMandate() throws EaafException, SpecificCommunicationException { + Map attr = new HashMap<>(); + attr.put(PvpAttributeDefinitions.BPK_NAME, + "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); + attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, RandomStringUtils.randomAlphabetic(10)); attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, RandomStringUtils.randomAlphabetic(10)); @@ -197,13 +271,13 @@ public class ProxyServiceAuthenticationActionTest { ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); assertEquals("wrong attr. size", 8, respAttr.size()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER, - (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER)); + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER, - (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER)); + (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME, (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME, @@ -213,19 +287,86 @@ public class ProxyServiceAuthenticationActionTest { } + @Test + public void responseWithNatMandateOptionalAttribute() throws EaafException, SpecificCommunicationException { + LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest(); + eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder() + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByName("http://eidas.europa.eu/attributes/naturalperson/BirthName")) + .build()); + pendingReq.setEidasRequest(eidasRequestBuilder.build()); + + Map attr = new HashMap<>(); + attr.put(PvpAttributeDefinitions.BPK_NAME, + "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); + attr.put("ida_birthName_mandator", RandomStringUtils.randomAlphanumeric(10)); + attr.put("ida_birthName", RandomStringUtils.randomAlphanumeric(10)); + + attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, + RandomStringUtils.randomAlphabetic(10)); + attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, + RandomStringUtils.randomAlphabetic(10)); + attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, + RandomStringUtils.randomAlphabetic(10)); + attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, + "1985-11-15"); + + + IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, + RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true); + + //perform test + SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData); + + //validate state + Assert.assertNotNull("Result should be not null", result); + + ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); + assertEquals("wrong attr. size", 9, respAttr.size()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER, + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName()); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth()); + + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER, + (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME)); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME, + (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME)); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME, + (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME)); + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_DATEOFBIRTH, + (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME)); + + checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_BIRTHNAME, + (String) attr.get("ida_birthName_mandator")); + + } + @Test public void responseWithJurMandate() throws EaafException, SpecificCommunicationException { Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.BPK_NAME, "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, RandomStringUtils.randomAlphabetic(10)); attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, RandomStringUtils.randomAlphabetic(10)); + LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest(); + eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder() + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_LEGALNAME).first()) + .build()); + pendingReq.setEidasRequest(eidasRequestBuilder.build()); + + //perform test SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData); @@ -235,13 +376,13 @@ public class ProxyServiceAuthenticationActionTest { ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); assertEquals("wrong attr. size", 6, respAttr.size()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER, - (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER)); + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_LEGALPERSONIDENTIFIER, - (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER)); + (String) attr.get(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_LEGALNAME, (String) attr.get(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME)); @@ -260,19 +401,12 @@ public class ProxyServiceAuthenticationActionTest { public void responseWithNatMandateWithWorkAround() throws EaafException, SpecificCommunicationException { basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson", "true"); - - //request natural person subject only - LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest(); - eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder().put( - attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build()); - pendingReq.setEidasRequest(eidasRequestBuilder.build()); - - + Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.BPK_NAME, "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, RandomStringUtils.randomAlphabetic(10)); attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, RandomStringUtils.randomAlphabetic(10)); @@ -306,16 +440,17 @@ public class ProxyServiceAuthenticationActionTest { eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder() .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()) .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_LEGALNAME).first()) .build()); pendingReq.setEidasRequest(eidasRequestBuilder.build()); Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.BPK_NAME, "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, RandomStringUtils.randomAlphabetic(10)); attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, RandomStringUtils.randomAlphabetic(10)); @@ -329,7 +464,7 @@ public class ProxyServiceAuthenticationActionTest { ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData); assertEquals("wrong attr. size", 10, respAttr.size()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER, - (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER)); + (String) attr.get(PvpAttributeDefinitions.BPK_NAME)); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName()); checkAttrValue(respAttr, EidasConstants.eIDAS_ATTR_DATEOFBIRTH, authData.getDateOfBirth()); @@ -344,18 +479,18 @@ public class ProxyServiceAuthenticationActionTest { //request natural person subject only LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest(); eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder() - .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName( - EidasConstants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_LEGALNAME).first()) .build()); pendingReq.setEidasRequest(eidasRequestBuilder.build()); Map attr = new HashMap<>(); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.BPK_NAME, "AT+XX:" + RandomStringUtils.randomAlphanumeric(10)); IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH, RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true); - attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, + attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, RandomStringUtils.randomAlphabetic(10)); attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, RandomStringUtils.randomAlphabetic(10)); @@ -390,7 +525,7 @@ public class ProxyServiceAuthenticationActionTest { } private IAuthData generateDummyAuthData() { - return generateDummyAuthData(Collections.emptyMap(), EaafConstants.EIDAS_LOA_LOW, + return generateDummyAuthData(new HashMap<>(), EaafConstants.EIDAS_LOA_LOW, RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1940-01-01", false); } @@ -445,12 +580,22 @@ public class ProxyServiceAuthenticationActionTest { .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase()) .spType("public") .requesterId(RandomStringUtils.randomAlphanumeric(10)) - .providerName(RandomStringUtils.randomAlphanumeric(10)); - + .providerName(RandomStringUtils.randomAlphanumeric(10)) + .requestedAttributes(ImmutableAttributeMap.builder() + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_PERSONALIDENTIFIER).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTGIVENNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_CURRENTFAMILYNAME).first()) + .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(EidasConstants.eIDAS_ATTR_DATEOFBIRTH).first()) + .build() + ); } private IAuthData generateDummyAuthData(Map attrs, String loa, String familyName, String givenName, String dateOfBirth, boolean useMandates) { + attrs.put(PvpAttributeDefinitions.BIRTHDATE_NAME, dateOfBirth); + attrs.put(PvpAttributeDefinitions.GIVEN_NAME_NAME, givenName); + attrs.put(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, familyName); + return new IEidAuthData() { @Override diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/services/ProxyEidasAttributeRegistryTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/services/ProxyEidasAttributeRegistryTest.java index d3e787bb..8d417c1a 100644 --- a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/services/ProxyEidasAttributeRegistryTest.java +++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/services/ProxyEidasAttributeRegistryTest.java @@ -1,11 +1,13 @@ package at.asitplus.eidas.specific.modules.msproxyservice.test.services; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; import org.apache.commons.lang3.RandomStringUtils; @@ -92,6 +94,39 @@ public class ProxyEidasAttributeRegistryTest { } + @Test + public void attributeResponseMapping() { + assertFalse("find wrong IDA mapping", attrRegistry.mapEidasAttributeToSpecificIdaAttribute( + "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", false).isPresent()); + assertFalse("find wrong IDA mapping", attrRegistry.mapEidasAttributeToSpecificIdaAttribute( + "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", true).isPresent()); + + + Optional attr1 = attrRegistry.mapEidasAttributeToSpecificIdaAttribute( + "http://eidas.europa.eu/attributes/naturalperson/BirthName", false); + assertTrue("find wrong IDA mapping", attr1.isPresent()); + assertEquals("find wrong IDA mapping value", "ida_birthname", attr1.get()); + + Optional attr2 = attrRegistry.mapEidasAttributeToSpecificIdaAttribute( + "http://eidas.europa.eu/attributes/naturalperson/BirthName", true); + assertTrue("find wrong IDA mapping", attr2.isPresent()); + assertEquals("find wrong IDA mapping value", "ida_birthName_mandator", attr2.get()); + + + assertTrue("find wrong IDA mapping", attrRegistry.mapEidasAttributeToSpecificIdaAttribute( + "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", false).isPresent()); + assertTrue("find wrong IDA mapping", attrRegistry.mapEidasAttributeToSpecificIdaAttribute( + "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", true).isPresent()); + + } + + @Test + public void defaultRepresentativeAttributes() { + assertEquals("wrong number of rep. attributes", 4, + attrRegistry.getRepresentativeAttributesToAddByDefault().count()); + + } + private void checkAttributeMapping(String eidasAttr, boolean withMandates, List idaAttributes) { @NonNull Set idaAttrResult = attrRegistry.getIdaAttributesForEidasAttribute(eidasAttr, withMandates); diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/idaAttributeMapping.json b/modules/eidas_proxy-sevice/src/test/resources/config/idaAttributeMapping.json index 2d375acb..7e41d8f6 100644 --- a/modules/eidas_proxy-sevice/src/test/resources/config/idaAttributeMapping.json +++ b/modules/eidas_proxy-sevice/src/test/resources/config/idaAttributeMapping.json @@ -6,7 +6,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.98" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": false } }, { @@ -16,7 +17,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.78" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": false } }, { @@ -26,7 +28,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.80" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": false } }, { @@ -36,21 +39,27 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.82" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": false } }, { "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", "idaAttribute": {}, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } }, { "eidasAttribute": "http://eidas.europa.eu/attributes/naturalperson/BirthName", - "idaAttribute": {}, + "idaAttribute": { + "basic": "ida_birthname", + "withMandates": "ida_birthName_mandator" + }, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } }, { @@ -65,7 +74,8 @@ "urn:oid:1.2.40.0.10.2.1.1.55" ], "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": false } }, { @@ -74,7 +84,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.84" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": false } }, { @@ -83,7 +94,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.149" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": true } }, { @@ -92,7 +104,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.20" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": true } }, { @@ -101,7 +114,8 @@ "withMandates": "urn:oid:2.5.4.42" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": true } }, { @@ -110,7 +124,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.55" }, "type": { - "mds": true + "mds": true, + "autoIncludeWithMandates": true } }, { @@ -120,7 +135,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.32" }, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } }, { @@ -130,7 +146,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.108" }, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } }, { @@ -139,7 +156,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.68" }, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } }, { @@ -148,7 +166,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.106" }, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } }, { @@ -157,7 +176,8 @@ "withMandates": "urn:oid:1.2.40.0.10.2.1.1.261.106" }, "type": { - "mds": false + "mds": false, + "autoIncludeWithMandates": false } } ] \ No newline at end of file diff --git a/ms_specific_connector/src/main/resources/specific_eIDAS_connector.beans.xml b/ms_specific_connector/src/main/resources/specific_eIDAS_connector.beans.xml index 9861a7c6..0757327a 100644 --- a/ms_specific_connector/src/main/resources/specific_eIDAS_connector.beans.xml +++ b/ms_specific_connector/src/main/resources/specific_eIDAS_connector.beans.xml @@ -14,6 +14,9 @@ + + diff --git a/ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/builder/ProxyAuthenticationDataBuilder.java b/ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/builder/ProxyAuthenticationDataBuilder.java new file mode 100644 index 00000000..bc7f88d4 --- /dev/null +++ b/ms_specific_proxyservice/src/main/java/at/asitplus/eidas/specific/proxy/builder/ProxyAuthenticationDataBuilder.java @@ -0,0 +1,38 @@ +package at.asitplus.eidas.specific.proxy.builder; + +import at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import lombok.extern.slf4j.Slf4j; + +/** + * eIDAS Proxy-Service specific authentication-data builder. + * + * @author tlenz + * + */ +@Slf4j +public class ProxyAuthenticationDataBuilder extends AuthenticationDataBuilder { + + private static final String PLUS = "+"; + + @Override + protected String customizeLegalPersonSourcePin(String sourcePin, String sourcePinType) { + String sectorType = sourcePinType.substring((EaafConstants.URN_PREFIX_BASEID + PLUS).length()); + return sectorType + PLUS + sourcePin; + + } + + @Override + protected String customizeBpkAttribute(String pvpBpkAttrValue) { + final String[] split = pvpBpkAttrValue.split(":", 2); + if (split.length == 2) { + log.debug("Remove prefix from bPK attribute to transform it into eIDAS-Node format"); + return split[1]; + + } else { + log.warn("PVP bPK attribute: {} has wrong format. Use it as it is.", pvpBpkAttrValue); + return pvpBpkAttrValue; + + } + } +} diff --git a/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml b/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml index 5633cb0e..cc4c904e 100644 --- a/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml +++ b/ms_specific_proxyservice/src/main/resources/specific_eIDAS_proxy.beans.xml @@ -13,6 +13,9 @@ + + diff --git a/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/builder/ProxyAuthenticationDataBuilderTest.java b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/builder/ProxyAuthenticationDataBuilderTest.java new file mode 100644 index 00000000..ee2c8d8c --- /dev/null +++ b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/builder/ProxyAuthenticationDataBuilderTest.java @@ -0,0 +1,395 @@ +package at.asitplus.eidas.specific.proxy.test.builder; + +import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.RandomUtils; +import org.apache.ignite.Ignition; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.InitializationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.google.common.collect.Sets; + +import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder; +import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration; +import at.gv.egiz.components.spring.api.SpringBootApplicationContextInitializer; +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.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication; +import lombok.SneakyThrows; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +@ContextConfiguration(initializers = { + org.springframework.boot.context.config.DelegatingApplicationContextInitializer.class, + SpringBootApplicationContextInitializer.class + }) +@TestPropertySource(locations = { "file:src/test/resources/config/junit_config_1_springboot.properties" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@ActiveProfiles(profiles = {"JUNIT", "jUnitTestMode"}) +public class ProxyAuthenticationDataBuilderTest { + + + @Autowired + private AuthenticationDataBuilder authenticationDataBuilder; + + @Autowired(required = true) + private IConfiguration basicConfig; + + private MockHttpServletRequest httpReq; + private MockHttpServletResponse httpResp; + private TestRequestImpl pendingReq; + + private Map spConfig; + private ServiceProviderConfiguration oaParam; + + private String eidasBind; + private String authBlock; + + @BeforeClass + public static void classInitializer() throws InitializationException, ComponentInitializationException { + final String current = new java.io.File(".").toURI().toString(); + System.setProperty("eidas.ms.configuration", current + + "src/test/resources/config/junit_config_3.properties"); + + //eIDAS Ref. Impl. properties + System.setProperty("EIDAS_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_CONNECTOR_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_PROXY_SERVICE_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + + EaafOpenSaml3xInitializer.eaafInitialize(); + } + + /** + * Test shut-down. + * + * @throws Exception In case of an error + */ + @AfterClass + @SneakyThrows + public static void closeIgniteNode() { + System.out.println("Closiong Ignite Node ... "); + Ignition.stopAll(true); + + //set Ignite-node holder to 'null' because static holders are shared between different tests + final Field field = IgniteInstanceInitializerSpecificCommunication.class.getDeclaredField("instance"); + field.setAccessible(true); + field.set(null, null); + + } + + @Before + @SneakyThrows + public void initialize() throws EaafStorageException { + httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + httpResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + + spConfig = new HashMap<>(); + spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp"); + spConfig.put("target", "urn:publicid:gv.at:cdid+XX"); + spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true"); + oaParam = new ServiceProviderConfiguration(spConfig, basicConfig); + oaParam.setBpkTargetIdentifier("urn:publicid:gv.at:cdid+XX"); + + pendingReq = new TestRequestImpl(); + pendingReq.setAuthUrl("https://localhost/ms_connector"); + pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); + pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10)); + pendingReq.setSpConfig(oaParam); + authBlock = RandomStringUtils.randomAlphanumeric(20); + eidasBind = RandomStringUtils.randomAlphanumeric(20); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, authBlock); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_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)); + + LocaleContextHolder.resetLocaleContext(); + + } + + @Test + @SneakyThrows + public void eidasProxyModeSimple() throws EaafAuthenticationException { + // initialize state + pendingReq = new TestRequestImpl(); + pendingReq.setAuthUrl("https://localhost/ms_connector"); + pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); + pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10)); + pendingReq.setSpConfig(oaParam); + boolean isTestIdentity = RandomUtils.nextBoolean(); + + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setForeigner(false); + + String bpk = RandomStringUtils.randomAlphanumeric(10); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.BPK_NAME, "eidas+AT+XX:" + bpk); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + "http://eidas.europa.eu/LoA/high"); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, + RandomStringUtils.randomAlphabetic(2)); + + String randAttr = RandomStringUtils.randomAlphabetic(10); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( + randAttr, RandomStringUtils.randomAlphabetic(10)); + + oaParam.setRequestedAttributes(Sets.newHashSet(randAttr, + PvpAttributeDefinitions.BPK_NAME, + PvpAttributeDefinitions.GIVEN_NAME_NAME, + PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, + PvpAttributeDefinitions.BIRTHDATE_NAME, + PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + PvpAttributeDefinitions.EID_ISSUING_NATION_NAME)); + + + // execute + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + // validate state + Assert.assertNotNull("AuthData null", authData); + Assert.assertNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class)); + Assert.assertNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class)); + Assert.assertNotNull("LoA null", authData.getEidasQaaLevel()); + + Assert.assertEquals("FamilyName", "Mustermann", authData.getFamilyName()); + Assert.assertEquals("GivenName", "Max", authData.getGivenName()); + Assert.assertEquals("DateOfBirth", "1940-01-01", authData.getDateOfBirth()); + + Assert.assertEquals("LoA", "http://eidas.europa.eu/LoA/high", authData.getEidasQaaLevel()); + Assert.assertEquals("EID-ISSUING-NATION", + pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession( + PvpAttributeDefinitions.EID_ISSUING_NATION_NAME), + authData.getCiticenCountryCode()); + + checkGenericAttribute(authData, PvpAttributeDefinitions.BPK_NAME, bpk); + checkGenericAttribute(authData, PvpAttributeDefinitions.GIVEN_NAME_NAME, "Max"); + checkGenericAttribute(authData, PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, "Mustermann"); + checkGenericAttribute(authData, PvpAttributeDefinitions.BIRTHDATE_NAME, "1940-01-01"); + + Assert.assertEquals("random optional attr.", + pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession( + randAttr), + authData.getGenericData(randAttr, String.class)); + + } + + + @Test + public void eidasProxyModeWithNatMandate() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String givenNameMandate = RandomStringUtils.randomAlphabetic(10); + String familyNameMandate = RandomStringUtils.randomAlphabetic(10); + String dateOfBirthMandate = "1957-09-15"; + String bpkMandate = RandomStringUtils.randomAlphanumeric(10); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, "AT+XX:" + bpkMandate); + + oaParam.setRequestedAttributes(Sets.newHashSet( + PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME)); + + // execute test + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + + // validate state + Assert.assertNotNull("AuthData null", authData); + assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate()); + + //check mandate informations + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "1957-09-15"); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate); + + } + + @Test + public void eidasProxyModeWithNatMandateWrongBpkFormat() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String givenNameMandate = RandomStringUtils.randomAlphabetic(10); + String familyNameMandate = RandomStringUtils.randomAlphabetic(10); + String dateOfBirthMandate = "1957-09-15"; + String bpkMandate = RandomStringUtils.randomAlphanumeric(10); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, dateOfBirthMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate); + + oaParam.setRequestedAttributes(Sets.newHashSet( + PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, + PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME)); + + // execute test + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + + // validate state + Assert.assertNotNull("AuthData null", authData); + assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate()); + + //check mandate informations + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, givenNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, familyNameMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, "1957-09-15"); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_NAT_PER_BPK_NAME, bpkMandate); + + } + + @Test + public void eidasProxyModeWithJurMandate() throws EaafAuthenticationException, EaafStorageException { + // initialize state + injectRepresentativeInfosIntoSession(); + + String commonMandate = RandomStringUtils.randomAlphabetic(10); + + // set constant country-code and sourcePin to check hashed eIDAS identifier + String sourcePinMandate = "asfdsadfsadfsafsdafsadfasr"; + spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EE"); + + // set nat. person mandate information + pendingReq.getSessionData(AuthProcessDataWrapper.class).setUseMandates(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, commonMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, sourcePinMandate); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, + EaafConstants.URN_PREFIX_BASEID + "+XFN"); + + oaParam.setRequestedAttributes(Sets.newHashSet( + PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, + PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME)); + + // execute test + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + + // validate state + Assert.assertNotNull("AuthData null", authData); + assertTrue("mandate flag", ((EidAuthenticationData)authData).isUseMandate()); + + //check mandate informations + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, commonMandate); + checkGenericAttribute(authData, PvpAttributeDefinitions.MANDATE_LEG_PER_SOURCE_PIN_NAME, "XFN+" + sourcePinMandate); + + } + + private void injectRepresentativeInfosIntoSession() throws EaafStorageException { + boolean isTestIdentity = RandomUtils.nextBoolean(); + pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + + String givenName = RandomStringUtils.randomAlphabetic(10); + String familyName = RandomStringUtils.randomAlphabetic(10); + String dateOfBirth = "1956-12-08"; + String bpk = RandomStringUtils.randomAlphanumeric(10); + String cc = pendingReq.getSessionData(AuthProcessDataWrapper.class) + .getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class); + String spC = RandomStringUtils.randomAlphabetic(2).toUpperCase(); + spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + cc + "+" + spC); + + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setForeigner(false); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.GIVEN_NAME_NAME, givenName); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, familyName); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.BIRTHDATE_NAME, dateOfBirth); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, bpk); + + //set LoA level attribute instead of explicit session-data + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel()); + pendingReq.getSessionData(AuthProcessDataWrapper.class).setQaaLevel(null); + + } + + private void checkGenericAttribute(IAuthData authData, String attrName, String expected) { + assertEquals("Wrong: " + attrName, expected, authData.getGenericData(attrName, String.class)); + + } + +} diff --git a/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties b/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties index 8cd77046..47d50191 100644 --- a/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties +++ b/ms_specific_proxyservice/src/test/resources/config/junit_config_1_springboot.properties @@ -69,7 +69,7 @@ eidas.ms.configuration.pvp.enable.entitycategories=false ############################################################################# ## MS-speccific eIDAS-Proxy-Service configuration - +eidas.ms.auth.eIDAS.proxy.attribute.mapping.config=./../../../../../basicConfig/ms-proxyservice/misc/idaAttributeMapping.json #### eIDAS ms-specific Proxy-Service configuration eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy diff --git a/pom.xml b/pom.xml index 309fab68..e469f680 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ 0.3 0.4 - 1.3.2 + 1.3.3-SNAPSHOT 2.5.13 2.5.6 -- cgit v1.2.3 From cab2ab4ddb85b305d77798073b868cf42a7e0111 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Wed, 8 Jun 2022 14:56:42 +0200 Subject: chore(core): minory style, test and validation fixes --- .../specific/core/config/ServiceProviderConfiguration.java | 2 +- .../specific/core/builder/AuthenticationDataBuilder.java | 8 ++++---- modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml | 11 +++++++++++ .../specific/modules/msproxyservice/dto/attributes/Type.java | 11 ++++++++--- .../test/protocol/EidasProxyServiceControllerTest.java | 2 +- .../eidas/specific/proxy/test/FullStartUpAndProcessTest.java | 2 +- 6 files changed, 26 insertions(+), 10 deletions(-) (limited to 'ms_specific_proxyservice/src/test/java') diff --git a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java index 2ecbf7d0..d2177323 100644 --- a/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java +++ b/modules/core_common_lib/src/main/java/at/asitplus/eidas/specific/core/config/ServiceProviderConfiguration.java @@ -55,7 +55,7 @@ public class ServiceProviderConfiguration extends SpConfigurationImpl { private List mandateProfiles; /** - * IDA specific requested attributes + * IDA specific requested attributes. */ @Getter @Setter diff --git a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java index 673b8ef5..5a8992b5 100644 --- a/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java +++ b/modules/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java @@ -102,7 +102,7 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder buildNatPersonInfos((EidAuthenticationData) authData, authProcessData); // handle mandate informations - buildMandateInformation((EidAuthenticationData) authData, pendingReq, authProcessData); + buildMandateInformation((EidAuthenticationData) authData, authProcessData); } else { throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: " @@ -172,7 +172,7 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder } } - private void buildMandateInformation(EidAuthenticationData authData, IRequest pendingReq, + private void buildMandateInformation(EidAuthenticationData authData, EidAuthProcessDataWrapper authProcessData) throws EaafAuthenticationException, EaafBuilderException, EaafStorageException { authData.setUseMandate(authProcessData.isMandateUsed()); @@ -182,7 +182,7 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder buildMandateInformationForEidasIncoming(); } else { - buildMandateInformationForEidasOutgoing(authData, pendingReq, authProcessData); + buildMandateInformationForEidasOutgoing(authData, authProcessData); } } @@ -204,7 +204,7 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder } - private void buildMandateInformationForEidasOutgoing(EidAuthenticationData authData, IRequest pendingReq, + private void buildMandateInformationForEidasOutgoing(EidAuthenticationData authData, EidAuthProcessDataWrapper authProcessData) throws EaafAuthenticationException, EaafBuilderException, EaafStorageException { log.debug("Find eIDAS outgoing process. Generated mandate-information for other country ... "); diff --git a/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml b/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml index cdc9fa95..22dbaa13 100644 --- a/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml +++ b/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml @@ -16,5 +16,16 @@ + + + + + + + + + + + diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java index f66bb799..6a06a5b5 100644 --- a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java +++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/dto/attributes/Type.java @@ -22,8 +22,7 @@ import lombok.Data; public class Type { /** - * true if this attribute is part of MDS, otherwise - * false + * true if this attribute is part of MDS, otherwise false. */ @JsonProperty("mds") private Boolean mds; @@ -50,7 +49,7 @@ public class Type { NONE("none"); private final String value; - private final static Map CONSTANTS = new HashMap<>(); + private static final Map CONSTANTS = new HashMap<>(); static { for (final Type.Mandator c : values()) { @@ -72,6 +71,12 @@ public class Type { return this.value; } + /** + * Build {@link Mandator} from textual representation. + * + * @param value textual representation + * @return Type of the mandator + */ @JsonCreator public static Type.Mandator fromValue(String value) { final Type.Mandator constant = CONSTANTS.get(value); diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/EidasProxyServiceControllerTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/EidasProxyServiceControllerTest.java index ef1abbcd..b491c2bf 100644 --- a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/EidasProxyServiceControllerTest.java +++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/msproxyservice/test/protocol/EidasProxyServiceControllerTest.java @@ -329,7 +329,7 @@ public class EidasProxyServiceControllerTest { assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty()); assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode()); - assertEquals("requested IDA attributes", 3, spConfig.getRequestedAttributes().size()); + assertEquals("requested IDA attributes", 4, spConfig.getRequestedAttributes().size()); } diff --git a/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java index bc6f5317..2fe7ee05 100644 --- a/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java +++ b/ms_specific_proxyservice/src/test/java/at/asitplus/eidas/specific/proxy/test/FullStartUpAndProcessTest.java @@ -384,7 +384,7 @@ public class FullStartUpAndProcessTest { assertEquals("wrong number of extension elements", 1, authnReq.getExtensions().getOrderedChildren().size()); assertEquals("wrong number of requested attributes", - 4, authnReq.getExtensions().getOrderedChildren().get(0).getOrderedChildren().size()); + 5, authnReq.getExtensions().getOrderedChildren().get(0).getOrderedChildren().size()); return authnReq.getID(); } -- cgit v1.2.3