diff options
Diffstat (limited to 'connector/src/test')
5 files changed, 580 insertions, 5 deletions
| diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/FullStartUpAndProcessTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/FullStartUpAndProcessTest.java new file mode 100644 index 00000000..5206c2e5 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/FullStartUpAndProcessTest.java @@ -0,0 +1,485 @@ +package at.asitplus.eidas.specific.connector.test; + +import static org.mockito.ArgumentMatchers.any; +import static org.powermock.api.mockito.PowerMockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Timer; + +import javax.xml.transform.TransformerException; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.ignite.Ignition; +import org.joda.time.DateTime; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +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.MarshallingException; +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.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +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.skjolberg.mockito.soap.SoapServiceRule; + +import at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController; +import at.asitplus.eidas.specific.connector.controller.Pvp2SProfileEndpoint; +import at.asitplus.eidas.specific.connector.provider.PvpEndPointCredentialProvider; +import at.asitplus.eidas.specific.connector.provider.PvpMetadataProvider; +import at.asitplus.eidas.specific.connector.test.saml2.Pvp2SProfileEndPointTest; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry; +import at.gv.egiz.components.spring.api.SpringBootApplicationContextInitializer; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +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 at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils.AssertionAttributeExtractor; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.light.ILightRequest; +import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; +import eu.eidas.auth.commons.tx.BinaryLightToken; +import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames; +import eu.eidas.specificcommunication.exception.SpecificCommunicationException; +import eu.eidas.specificcommunication.protocol.SpecificCommunicationService; +import lombok.val; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import szrservices.SZR; +import szrservices.SignContentEntry; +import szrservices.SignContentResponseType; + +@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", "springBoot"}) +public class FullStartUpAndProcessTest { + +  private static final String FINAL_REDIRECT = "http://localhost/finalizeAuthProtocol?pendingid="; +   +  @Autowired private WebApplicationContext wac; +  @Autowired private PvpEndPointCredentialProvider credentialProvider; +  @Autowired private PvpMetadataProvider metadataProvider; +  @Autowired private ResourceLoader resourceLoader; +  @Autowired private EidasAttributeRegistry attrRegistry; +   +  @Autowired private Pvp2SProfileEndpoint sProfile; +  @Autowired private ProcessEngineSignalController signal; +  @Autowired private EidasSignalServlet eidasSignal; +  @Autowired private ProtocolFinalizationController finalize; +   +  @Rule +  public final SoapServiceRule soap = SoapServiceRule.newInstance(); +   +  private SZR szrMock; +   +  private String cc; +  private String givenName; +  private String familyName; +  private String dateOfBirth; +  private String personalId; +  private String vsz; +  private String eidasBind; +   +   +  /** +   * 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 +  public static void classInitializer() throws InterruptedException, InitializationException, ComponentInitializationException { +    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 IOException In case of an error +   */ +  @AfterClass +  public static void closeIgniteNode() throws IOException { +    System.out.println("Closiong Ignite Node ... "); +    Ignition.stopAll(true); + +  } + +  /** +   * jUnit test set-up. +   * +   * +   */ +  @Before +  public void setup() throws IOException { +    DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac); +    @SuppressWarnings("rawtypes") +    Map<String, FilterRegistrationBean> filters = wac.getBeansOfType(FilterRegistrationBean.class); +    for (FilterRegistrationBean<?> filter : filters.values()) { +      if (filter.isEnabled()) { +        builder.addFilter(filter.getFilter(), "/*"); +       +      } +    } + +    szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr"); +     +     +     +    cc = RandomStringUtils.randomAlphabetic(2).toUpperCase(); +    personalId = cc + "/AT/" + RandomStringUtils.randomNumeric(64); +    familyName = RandomStringUtils.randomAlphabetic(10); +    givenName = RandomStringUtils.randomAlphabetic(10); +    dateOfBirth = "2015-10-12"; +     +    vsz = RandomStringUtils.randomNumeric(10); +    eidasBind = RandomStringUtils.randomAlphanumeric(50); +     +  } +   +  @Test +  public void userStopProcess() throws UnsupportedEncodingException, XMLParserException, UnmarshallingException,  +      TransformerException, IOException, MarshallingException, ComponentInitializationException, EaafException { +    //start authentication process by sending a SAML2 Authn-Request +    MockHttpServletRequest saml2Req = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    injectSaml2AuthnReq(saml2Req); +    MockHttpServletResponse selectCountryResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(saml2Req, selectCountryResp)); +     +    // send SAML2 AuthnRequest  +    sProfile.pvpIdpPostRequest(saml2Req, selectCountryResp); +     +    //check country-selection response +    Assert.assertEquals("no country-selection page", 200, selectCountryResp.getStatus()); +    Assert.assertEquals("cc-selection page", "text/html;charset=UTF-8", selectCountryResp.getContentType()); +    String selectionPage = selectCountryResp.getContentAsString(); +    Assert.assertNotNull("selectionPage is null", selectionPage); +    Assert.assertFalse("selectionPage is empty", selectionPage.isEmpty()); +     +    String pendingReqId = extractRequestToken(selectionPage,  +        "<input  type=\"hidden\" name=\"pendingid\"  value=\""); +    Assert.assertFalse("PendingReqId", pendingReqId.isEmpty()); +     +     +    // set-up user-stop request +    MockHttpServletRequest userStopReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    userStopReq.setParameter("pendingid", pendingReqId); +    userStopReq.setParameter(EaafConstants.PARAM_HTTP_STOP_PROCESS, "true"); +     +    MockHttpServletResponse finalizeResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(userStopReq, finalizeResp)); +     +    // send user-stop request +    signal.performGenericAuthenticationProcess(userStopReq, finalizeResp); +     +    //validate state +    Assert.assertEquals("forward to finalization", 302, finalizeResp.getStatus()); +    Assert.assertNotNull("missing redirect header", finalizeResp.getHeader("Location")); +    Assert.assertTrue("wrong redirect header", finalizeResp.getHeader("Location").startsWith(FINAL_REDIRECT)); +    String finalPendingReqId = finalizeResp.getHeader("Location").substring(FINAL_REDIRECT.length()); +    Assert.assertFalse("final pendingRequestId", finalPendingReqId.isEmpty()); +     +    //set-up finalization request +    MockHttpServletRequest finalizationReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    finalizationReq.setParameter("pendingid", finalPendingReqId); +     +    MockHttpServletResponse saml2Resp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(finalizationReq, saml2Resp)); +     +    // exexcute finalization step +    finalize.finalizeAuthProtocol(finalizationReq, saml2Resp); +     +    //validate state +    Assert.assertEquals("forward to finalization", 200, saml2Resp.getStatus()); +    Assert.assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", saml2Resp.getContentType()); +    String saml2RespPage = saml2Resp.getContentAsString(); +    Assert.assertNotNull("selectionPage is null", saml2RespPage); +    Assert.assertFalse("selectionPage is empty", saml2RespPage.isEmpty()); +     +    //validate SAML2 response +    String saml2RespB64 = extractRequestToken(saml2RespPage,  +        "<input type=\"hidden\" name=\"SAMLResponse\" value=\""); +    Assert.assertNotNull("SAML2 response", saml2RespB64); +     +    StatusResponseType saml2 = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(),  +        new ByteArrayInputStream(Base64Utils.decodeFromString(saml2RespB64))); +    Assert.assertEquals("SAML2 status", "urn:oasis:names:tc:SAML:2.0:status:Responder",  +        saml2.getStatus().getStatusCode().getValue()); +    Assert.assertEquals("ms-connector status", "1005",  +        saml2.getStatus().getStatusCode().getStatusCode().getValue()); +     +  } +   +  @Test +  public void fullSuccessProcess() throws EaafException, Exception { +    //start authentication process by sending a SAML2 Authn-Request +    MockHttpServletRequest saml2Req = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    injectSaml2AuthnReq(saml2Req); +    MockHttpServletResponse selectCountryResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(saml2Req, selectCountryResp)); +     +    // send SAML2 AuthnRequest  +    sProfile.pvpIdpPostRequest(saml2Req, selectCountryResp); +     +    //check country-selection response +    Assert.assertEquals("no country-selection page", 200, selectCountryResp.getStatus()); +    Assert.assertEquals("cc-selection page", "text/html;charset=UTF-8", selectCountryResp.getContentType()); +    String selectionPage = selectCountryResp.getContentAsString(); +    Assert.assertNotNull("selectionPage is null", selectionPage); +    Assert.assertFalse("selectionPage is empty", selectionPage.isEmpty()); +     +    String pendingReqId = extractRequestToken(selectionPage,  +        "<input  type=\"hidden\" name=\"pendingid\"  value=\""); +    Assert.assertFalse("PendingReqId", pendingReqId.isEmpty()); +     +     +    // set-up country-selection request +    MockHttpServletRequest selectCountryReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    selectCountryReq.setParameter("pendingid", pendingReqId); +    selectCountryReq.setParameter("selectedCountry", cc); +     +    MockHttpServletResponse forwardEidasNodeResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(selectCountryReq, forwardEidasNodeResp)); +     +    // send country-selection request +    signal.performGenericAuthenticationProcess(selectCountryReq, forwardEidasNodeResp); +     +    //check forward to eIDAS node response +    Assert.assertEquals("forward to eIDAS Node", 200, forwardEidasNodeResp.getStatus()); +    Assert.assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", forwardEidasNodeResp.getContentType()); +    String forwardPage = forwardEidasNodeResp.getContentAsString(); +    Assert.assertNotNull("forward to eIDAS Node is null", forwardPage); +    Assert.assertFalse("forward to eIDAS Node is empty", forwardPage.isEmpty()); +     +    String eidasNodeReqToken = extractRequestToken(forwardPage,  +        "<input type=\"hidden\" name=\"token\" value=\""); +    Assert.assertFalse("eidas req. token", eidasNodeReqToken.isEmpty()); +     +    //check eIDAS node request and build respose +    String eidasRespToken = validateEidasNodeRequestAndBuildResponse(eidasNodeReqToken); +    Assert.assertFalse("eidas resp. token", eidasRespToken.isEmpty()); +     +     +    // set-up eIDAS-node response +    MockHttpServletRequest eidasNodeRespReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    eidasNodeRespReq.setParameter("token", eidasRespToken); +     +    MockHttpServletResponse finalizeResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(eidasNodeRespReq, finalizeResp)); +     +    injectSzrResponse(); +     +    //excute eIDAS node response +    eidasSignal.restoreEidasAuthProcess(eidasNodeRespReq, finalizeResp); +     +    //validate state +    Assert.assertEquals("forward to finalization", 302, finalizeResp.getStatus()); +    Assert.assertNotNull("missing redirect header", finalizeResp.getHeader("Location")); +    Assert.assertTrue("wrong redirect header", finalizeResp.getHeader("Location").startsWith(FINAL_REDIRECT)); +    String finalPendingReqId = finalizeResp.getHeader("Location").substring(FINAL_REDIRECT.length()); +    Assert.assertFalse("final pendingRequestId", finalPendingReqId.isEmpty()); +     +     +    //set-up finalization request +    MockHttpServletRequest finalizationReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    finalizationReq.setParameter("pendingid", finalPendingReqId); +     +    MockHttpServletResponse saml2Resp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(finalizationReq, saml2Resp)); +     +    // exexcute finalization step +    finalize.finalizeAuthProtocol(finalizationReq, saml2Resp); +     +    //validate state +    Assert.assertEquals("forward to finalization", 200, saml2Resp.getStatus()); +    Assert.assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", saml2Resp.getContentType()); +    String saml2RespPage = saml2Resp.getContentAsString(); +    Assert.assertNotNull("selectionPage is null", saml2RespPage); +    Assert.assertFalse("selectionPage is empty", saml2RespPage.isEmpty()); +     +    //validate SAML2 response +    String saml2RespB64 = extractRequestToken(saml2RespPage,  +        "<input type=\"hidden\" name=\"SAMLResponse\" value=\""); +    Assert.assertNotNull("SAML2 response", saml2RespB64); +     +    StatusResponseType saml2 = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(),  +        new ByteArrayInputStream(Base64Utils.decodeFromString(saml2RespB64))); +    Assert.assertEquals("SAML2 status", Constants.SUCCESS_URI, saml2.getStatus().getStatusCode().getValue()); +     +    final AssertionAttributeExtractor extractor = new AssertionAttributeExtractor(saml2); +    Assert.assertEquals("wrong resp attr. size", 6, extractor.getAllIncludeAttributeNames().size()); +    Assert.assertEquals("Wrong attr: LoA ", "http://eidas.europa.eu/LoA/high",  +        extractor.getSingleAttributeValue("urn:oid:1.2.40.0.10.2.1.1.261.108")); +    Assert.assertEquals("Wrong attr: PVP_VERSION ", "2.2",  +        extractor.getSingleAttributeValue("urn:oid:1.2.40.0.10.2.1.1.261.10")); +    Assert.assertEquals("Wrong attr: EID_ISSUER_NATION  ", cc,  +        extractor.getSingleAttributeValue("urn:oid:1.2.40.0.10.2.1.1.261.32")); +    Assert.assertEquals("Wrong attr: eidasBind", eidasBind,  +        extractor.getSingleAttributeValue("urn:eidgvat:attributes.eidbind")); +    Assert.assertNotNull("Wrong attr:  authBlock",  +        extractor.getSingleAttributeValue("urn:eidgvat:attributes.authblock.signed")); +    Assert.assertNotNull("Wrong attr: piiTras.Id ",  +        extractor.getSingleAttributeValue("urn:eidgvat:attributes.piiTransactionId")); +     +  } + +  private void injectSzrResponse() throws Exception { +     +    when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(vsz); +    val signContentResp = new SignContentResponseType(); +    final SignContentEntry signContentEntry = new SignContentEntry(); +    signContentEntry.setValue(eidasBind); +    signContentResp.getOut().add(signContentEntry); +    when(szrMock, "signContent", any(), any(), any()).thenReturn(signContentResp); +     +  } + +  private String validateEidasNodeRequestAndBuildResponse(String eidasNodeReqToken)  +      throws SpecificCommunicationException, URISyntaxException { +    final SpecificCommunicationService springManagedSpecificConnectorCommunicationService = +        (SpecificCommunicationService) wac.getBean( +            SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString()); +     +    //read request and validate basic properties  +    ILightRequest req = springManagedSpecificConnectorCommunicationService.getAndRemoveRequest(eidasNodeReqToken,  +        attrRegistry.getCoreAttributeRegistry().getAttributes()); +     +    Assert.assertNotNull("eIDAS Node req", req); +    Assert.assertEquals("Wrong CC", cc, req.getCitizenCountryCode()); +    Assert.assertEquals("Wrong CC", EaafConstants.EIDAS_LOA_SUBSTANTIAL, req.getLevelOfAssurance()); +     +     +    //set response from eIDAS node +    BinaryLightToken respoToken = springManagedSpecificConnectorCommunicationService.putResponse( +        buildDummyAuthResponse(Constants.SUCCESS_URI, req.getId())); +    return Base64Utils.encodeToString(respoToken.getTokenBytes()); +     +  } + +  private AuthenticationResponse buildDummyAuthResponse(String statusCode, String reqId) throws URISyntaxException { +    final AttributeDefinition attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( +        Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); +    final AttributeDefinition attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( +        Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); +    final AttributeDefinition attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( +        Constants.eIDAS_ATTR_CURRENTGIVENNAME).first(); +    final AttributeDefinition attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( +        Constants.eIDAS_ATTR_DATEOFBIRTH).first(); +    +    final ImmutableAttributeMap attributeMap = ImmutableAttributeMap.builder() +        .put(attributeDef, personalId) +        .put(attributeDef2, familyName) +        .put(attributeDef3, givenName) +        .put(attributeDef4, dateOfBirth).build(); + +    val b = new AuthenticationResponse.Builder(); +    return b.id("_".concat(Random.nextHexRandom16())) +        .issuer(RandomStringUtils.randomAlphabetic(10)) +        .subject(RandomStringUtils.randomAlphabetic(10)) +        .statusCode(statusCode) +        .inResponseTo(reqId) +        .subjectNameIdFormat("afaf") +        .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH) +        .attributes(attributeMap) +        .build(); +     +  } +   +  private String extractRequestToken(String selectionPage, String selector) { +    int start = selectionPage.indexOf(selector); +    Assert.assertTrue("find no pendingReqId location start", start > 0); +    int end = selectionPage.indexOf("\"", start + selector.length()); +    Assert.assertTrue("find no pendingReqId location end", end > 0); +    return selectionPage.substring(start + selector.length(), end); +     +  } + +  private void injectSaml2AuthnReq(MockHttpServletRequest saml2Req) throws XMLParserException, UnmarshallingException,  +      SamlSigningException, CredentialsNotAvailableException, UnsupportedEncodingException, TransformerException,  +      IOException, MarshallingException, ComponentInitializationException { +    final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        Pvp2SProfileEndPointTest.class.getResourceAsStream("/data/pvp2_authn_1.xml")); +    authnReq.setIssueInstant(DateTime.now());     +    RequestAbstractType signedAuthnReq =  +        Saml2Utils.signSamlObject(authnReq, credentialProvider.getMessageSigningCredential(), true);            +    String b64 = Base64Utils.encodeToString(DomUtils.serializeNode( +          XMLObjectSupport.getMarshaller(signedAuthnReq).marshall(signedAuthnReq)).getBytes("UTF-8"));     +    saml2Req.setParameter("SAMLRequest", b64); +             +    final org.springframework.core.io.Resource resource = resourceLoader.getResource( +        "classpath:/data/metadata_valid_without_encryption.xml"); +    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();                     +    metadataProvider.addMetadataResolverIntoChain(fileSystemResolver); +     +  } +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java index 66147971..5fd39383 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java @@ -81,7 +81,7 @@ public class MainClassExecutableModeTest {    @Test -  public void validConfigLocation() throws ClientProtocolException, IOException { +  public void validConfigLocation() throws Throwable {      SpringBootApplicationInitializer          .main(new String[] {              "--spring.config.location=src/test/resources/config/junit_config_1_springboot.properties,classpath:/application.properties", diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java index 265edfb6..ae0a45db 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java @@ -72,7 +72,7 @@ public class MainClassWebAppModeTest {    }    @Test -  public void wrongConfigLocation() { +  public void wrongConfigLocation() throws Throwable {      //MS-specific connector property      final String current = new java.io.File(".").toURI().toString();      System.setProperty("eidas.ms.configuration", current @@ -93,7 +93,7 @@ public class MainClassWebAppModeTest {    @Test -  public void systemdConfigLocation() throws ClientProtocolException, IOException {     +  public void systemdConfigLocation() throws Throwable {          //MS-specific connector property      final String current = new java.io.File(".").toURI().toString();      System.setProperty("eidas.ms.configuration", current diff --git a/connector/src/test/resources/config/junit_config_1_springboot.properties b/connector/src/test/resources/config/junit_config_1_springboot.properties index 7257df9b..ecb22dec 100644 --- a/connector/src/test/resources/config/junit_config_1_springboot.properties +++ b/connector/src/test/resources/config/junit_config_1_springboot.properties @@ -19,7 +19,7 @@ eidas.ms.monitoring.eIDASNode.metadata.url=  eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret  ## eIDAS Ref. Implementation connector ### -eidas.ms.auth.eIDAS.node_v2.forward.endpoint= +eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://eidas.node/junit  eidas.ms.auth.eIDAS.szrclient.useTestService=true  eidas.ms.auth.eIDAS.szrclient.endpoint.prod= @@ -40,7 +40,7 @@ eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s  #Raw eIDAS Id data storage  eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true -eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true +eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false @@ -66,6 +66,8 @@ eidas.ms.sp.0.uniqueID=https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/met  eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks  eidas.ms.sp.0.pvp2.metadata.truststore.password=password  eidas.ms.sp.0.friendlyName=jUnit test +eidas.ms.sp.0.newEidMode=true +  #eidas.ms.sp.0.pvp2.metadata.url=  #eidas.ms.sp.0.policy.allowed.requested.targets=.*  #eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false diff --git a/connector/src/test/resources/data/metadata_valid_without_encryption.xml b/connector/src/test/resources/data/metadata_valid_without_encryption.xml new file mode 100644 index 00000000..b224c336 --- /dev/null +++ b/connector/src/test/resources/data/metadata_valid_without_encryption.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b67c160c0ad7b4ebd430581df167ac23" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"> +  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +    <ds:SignedInfo> +      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> +      <ds:Reference URI="#_b67c160c0ad7b4ebd430581df167ac23"> +        <ds:Transforms> +          <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +          <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +        </ds:Transforms> +        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> +        <ds:DigestValue>00SaL0XjeknOb/DttutP50lTyAux1jaRPJIVdSupWvU=</ds:DigestValue> +      </ds:Reference> +    </ds:SignedInfo> +    <ds:SignatureValue>PfEBmLMX/ZgL6ViXghyWtal5MaMoW8k3zjw+54+WK1OAtVsVgOsIDRJE0M/a/VXBbMSifgY6J1gN23xhr61jkrjRQEkbDzLpWZLzWAJ65YqqUQo8wsKI2Gz0j12yY5D8/GOamKOH9KDi5ba1veXR/fnxRINoy7nZo4tcUWZChdl8BWkMN5ugr6dORNIQg/Ym3GabQ/hR5z+9FmveAKphdH63MC6qW3EgM9EMvOVkrLBTP92sNMAAJeaawui9tlxi9anVQ0OqwZsgKLvI7fyV4CM/0sd/ELjeReIlWlHk07Nz4eltMq3eOx3q1YurYvhE8XapHiQMehOtCS+Fzh10sw==</ds:SignatureValue> +    <ds:KeyInfo> +      <ds:X509Data> +        <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> +      </ds:X509Data> +    </ds:KeyInfo> +  </ds:Signature> +  <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> +    <md:KeyDescriptor use="signing"> +      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +        <ds:X509Data> +          <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L</ds:X509Certificate> +        </ds:X509Data> +      </ds:KeyInfo> +    </md:KeyDescriptor> +    <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> +    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> +    <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> +    <md:AttributeConsumingService index="0" isDefault="true"> +      <md:ServiceName xml:lang="en">Default Service</md:ServiceName> +      <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +      <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +      <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> +      <md:RequestedAttribute FriendlyName="userAuthBlock" Name="urn:eidgvat:attributes.authblock.signed" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +      <md:RequestedAttribute FriendlyName="piiTransactionId" Name="urn:eidgvat:attributes.piiTransactionId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> +    </md:AttributeConsumingService> +  </md:SPSSODescriptor> +  <md:Organization> +    <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> +    <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> +    <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> +  </md:Organization> +  <md:ContactPerson contactType="technical"> +    <md:Company>E-Government Innovationszentrum</md:Company> +    <md:GivenName>Lenz</md:GivenName> +    <md:SurName>Thomas</md:SurName> +    <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> +    <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> +  </md:ContactPerson> +</md:EntityDescriptor> | 
