package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; import static at.asitplus.eidas.specific.connector.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE; import static org.mockito.ArgumentMatchers.any; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.apache.commons.lang3.RandomStringUtils; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import com.github.skjolber.mockito.soap.SoapServiceRule; import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyConfigMap; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry; import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IRequestStorage; import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; import at.gv.egiz.eaaf.core.api.data.EaafConstants; import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration; import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; import at.gv.egiz.eaaf.core.impl.utils.Random; import eu.eidas.auth.commons.attribute.AttributeDefinition; import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; import lombok.val; import szrservices.GetBPK; import szrservices.GetBPKResponse; import szrservices.GetIdentityLinkEidasResponse; import szrservices.PersonInfoType; import szrservices.SZR; import szrservices.SZRException_Exception; @RunWith(SpringJUnit4ClassRunner.class) @PrepareForTest(CreateIdentityLinkTask.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) @ContextConfiguration(locations = { "/SpringTest-context_tasks_test.xml", "/SpringTest-context_basic_mapConfig.xml"}) public class CreateIdentityLinkTaskTest { @Autowired(required = true) private CreateIdentityLinkTask task; @Autowired(required = true) private MsConnectorDummyConfigMap basicConfig; @Autowired protected EidasAttributeRegistry attrRegistry; @Autowired EaafKeyStoreFactory keyStoreFactory; @Autowired private IRequestStorage requestStorage; final ExecutionContext executionContext = new ExecutionContextImpl(); private MockHttpServletRequest httpReq; private MockHttpServletResponse httpResp; private TestRequestImpl pendingReq; private DummySpConfiguration oaParam; private SZR szrMock; private AuthenticationResponse response; private Map spConfig; @Rule public final SoapServiceRule soap = SoapServiceRule.newInstance(); /** * jUnit test set-up. */ @Before public void setUp() throws EaafStorageException, URISyntaxException { httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); httpResp = new MockHttpServletResponse(); RequestContextHolder.resetRequestAttributes(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation", "false"); spConfig = new HashMap<>(); spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp"); spConfig.put("target", "urn:publicid:gv.at:cdid+XX"); spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "false"); oaParam = new DummySpConfiguration(spConfig, basicConfig); pendingReq = new TestRequestImpl(); response = buildDummyAuthResponse(); pendingReq.getSessionData(AuthProcessDataWrapper.class) .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response); pendingReq.setSpConfig(oaParam); pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue()); pendingReq.setAuthUrl("http://test.com/"); pendingReq.setTransactionId("avaasbav"); pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10)); executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "XX"); executionContext.put(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT, true); szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr"); } @Test public void buildIdentityLink() throws Exception { //initialize test setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml"); String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); //perform test task.execute(pendingReq, executionContext); //validate state // check if pendingRequest was stored IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId()); Assert.assertNotNull("pendingReq not stored", storedPendingReq); //check data in session final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class); Assert.assertNotNull("AuthProcessData", authProcessData); Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); Assert.assertNull("AuthBlock", authBlock); Assert.assertFalse("EID process", authProcessData.isEidProcess()); Assert.assertTrue("foreigner process", authProcessData.isForeigner()); Assert.assertEquals("EID-ISSUING_NATION", "LU", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class)); Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel()); Assert.assertEquals("LoA", response.getLevelOfAssurance(), authProcessData.getQaaLevel()); Assert.assertNotNull("IDL", authProcessData.getIdentityLink()); checkElement("Mustermann", authProcessData.getIdentityLink().getFamilyName()); checkElement("Hans", authProcessData.getIdentityLink().getGivenName()); checkElement("1989-05-05", authProcessData.getIdentityLink().getDateOfBirth()); checkElement("urn:publicid:gv.at:baseid", authProcessData.getIdentityLink().getIdentificationType()); checkElement("k+zDM1BVpN1WJO4x7ZQ3ng==", authProcessData.getIdentityLink().getIdentificationValue()); Assert.assertNotNull(authProcessData.getIdentityLink().getSerializedSamlAssertion()); Assert.assertNotNull(authProcessData.getIdentityLink().getSamlAssertion()); Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); Assert.assertEquals("wrong bPK", "XX:FkXtOaSSeR3elyL9KLLvijIYDMU=", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); } @Test public void buildIdentityLinkWithWbpk() throws Exception { //initialize test setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml"); spConfig.put("target", EaafConstants.URN_PREFIX_WBPK + "FN+123456i"); String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true"); //perform test task.execute(pendingReq, executionContext); //validate state // check if pendingRequest was stored IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId()); Assert.assertNotNull("pendingReq not stored", storedPendingReq); //check data in session final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class); Assert.assertNotNull("AuthProcessData", authProcessData); Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); Assert.assertNull("AuthBlock", authBlock); Assert.assertFalse("EID process", authProcessData.isEidProcess()); Assert.assertTrue("foreigner process", authProcessData.isForeigner()); Assert.assertEquals("EID-ISSUING_NATION", "LU", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class)); Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel()); Assert.assertEquals("LoA", response.getLevelOfAssurance(), authProcessData.getQaaLevel()); Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); Assert.assertEquals("wrong bPK", "FN+123456i:D26vJncPS2W790RH/LP04V+vNOQ=", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); } @Test public void buildIdentityLinkWithEidasBpk() throws Exception { //initialize test setSzrResponseIdentityLink("/data/szr/szr_resp_valid_2.xml"); spConfig.put("target", EaafConstants.URN_PREFIX_EIDAS + "AT+EU"); String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true"); //perform test task.execute(pendingReq, executionContext); //validate state // check if pendingRequest was stored IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId()); Assert.assertNotNull("pendingReq not stored", storedPendingReq); //check data in session final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class); Assert.assertNotNull("AuthProcessData", authProcessData); Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); Assert.assertNull("AuthBlock", authBlock); Assert.assertFalse("EID process", authProcessData.isEidProcess()); Assert.assertTrue("foreigner process", authProcessData.isForeigner()); Assert.assertEquals("EID-ISSUING_NATION", "LU", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class)); Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel()); Assert.assertEquals("LoA", response.getLevelOfAssurance(), authProcessData.getQaaLevel()); Assert.assertNotNull("IDL", authProcessData.getIdentityLink()); checkElement("Musterfrau", authProcessData.getIdentityLink().getFamilyName()); checkElement("Martina", authProcessData.getIdentityLink().getGivenName()); checkElement("1991-04-15", authProcessData.getIdentityLink().getDateOfBirth()); checkElement("urn:publicid:gv.at:baseid", authProcessData.getIdentityLink().getIdentificationType()); checkElement("k+zDM1BV1312312332x7ZQ3ng==", authProcessData.getIdentityLink().getIdentificationValue()); Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); Assert.assertEquals("wrong bPK", "AT+EU:AT/EU/1+wqDl059/02Ptny0g+LyuLDJV0=", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); } @Test public void buildIdentityLinkWithUnknownBpk() throws Exception { //initialize test setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml"); spConfig.put("target", "urn:notextis:1234"); String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true"); try { task.execute(pendingReq, executionContext); Assert.fail("unknown bPKType not detected"); } catch (TaskExecutionException e) { Assert.assertEquals("ErrorId", "builder.33", ((EaafException) e.getOriginalException()).getErrorId()); Assert.assertEquals("wrong parameter size", 1, ((EaafException) e.getOriginalException()) .getParams().length); } } @Test public void noBpkResult() throws Exception { //initialize test setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml"); GetBPKResponse getBpkResp = new GetBPKResponse(); org.mockito.Mockito.when(szrMock.getBPK(any(GetBPK.class))).thenReturn(getBpkResp ); spConfig.put("target", "urn:notextis:1234"); String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation", "true"); try { task.execute(pendingReq, executionContext); Assert.fail("unknown bPKType not detected"); } catch (TaskExecutionException e) { Assert.assertEquals("ErrorId", "ernb.01", ((EaafException) e.getOriginalException()).getErrorId()); } } @Test public void bPKFromSzr() throws Exception { //initialize test setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml"); String bpk = RandomStringUtils.randomAlphanumeric(10); GetBPKResponse getBpkResp = new GetBPKResponse(); getBpkResp.getGetBPKReturn().add(bpk); org.mockito.Mockito.when(szrMock.getBPK(any(GetBPK.class))).thenReturn(getBpkResp ); spConfig.put("target", "urn:notextis:1234"); String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "false"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.revisionlog.eidmapping.active", "true"); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation", "true"); //execute test task.execute(pendingReq, executionContext); //validate state // check if pendingRequest was stored IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId()); Assert.assertNotNull("pendingReq not stored", storedPendingReq); //check data in session final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class); Assert.assertNotNull("AuthProcessData", authProcessData); Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); Assert.assertNull("AuthBlock", authBlock); Assert.assertFalse("EID process", authProcessData.isEidProcess()); Assert.assertTrue("foreigner process", authProcessData.isForeigner()); Assert.assertEquals("EID-ISSUING_NATION", "LU", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class)); Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel()); Assert.assertEquals("LoA", response.getLevelOfAssurance(), authProcessData.getQaaLevel()); Assert.assertNotNull("no bPK", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); Assert.assertEquals("wrong bPK", bpk, authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME)); } @Test public void buildDummyIdl() throws Exception { //initialize test String randomTestSp = RandomStringUtils.randomAlphabetic(10); pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "true"); //perform test task.execute(pendingReq, executionContext); //validate state // check if pendingRequest was stored IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId()); Assert.assertNotNull("pendingReq not stored", storedPendingReq); //check data in session final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class); Assert.assertNotNull("AuthProcessData", authProcessData); Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); Assert.assertNull("AuthBlock", authBlock); Assert.assertFalse("EID process", authProcessData.isEidProcess()); Assert.assertTrue("foreigner process", authProcessData.isForeigner()); Assert.assertEquals("EID-ISSUING_NATION", "LU", authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class)); Assert.assertNotNull("LoA is null", authProcessData.getQaaLevel()); Assert.assertEquals("LoA", response.getLevelOfAssurance(), authProcessData.getQaaLevel()); Assert.assertNotNull("IDL", authProcessData.getIdentityLink()); } private void setSzrResponseIdentityLink(String responseXmlPath) throws JAXBException, SZRException_Exception { final JAXBContext jaxbContext = JAXBContext .newInstance(szrservices.ObjectFactory.class, org.w3._2001._04.xmldsig_more.ObjectFactory.class, org.w3._2000._09.xmldsig.ObjectFactory.class, at.gv.e_government.reference.namespace.persondata._20020228.ObjectFactory.class); final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); final GetIdentityLinkEidasResponse szrResponse = (GetIdentityLinkEidasResponse) jaxbUnmarshaller .unmarshal(this.getClass().getResourceAsStream(responseXmlPath)); org.mockito.Mockito.when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenReturn(szrResponse.getGetIdentityLinkReturn()); } private void checkElement(String expected, String value) { Assert.assertNotNull(value); Assert.assertEquals(expected, value); } @NotNull private AuthenticationResponse buildDummyAuthResponse() throws URISyntaxException { final AttributeDefinition attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); final AttributeDefinition attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); final AttributeDefinition attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( Constants.eIDAS_ATTR_CURRENTGIVENNAME).first(); final AttributeDefinition attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( Constants.eIDAS_ATTR_DATEOFBIRTH).first(); final ImmutableAttributeMap attributeMap = ImmutableAttributeMap.builder() .put(attributeDef, "LU/AT/" + RandomStringUtils.randomNumeric(64)) .put(attributeDef2, RandomStringUtils.randomAlphabetic(10)) .put(attributeDef3, RandomStringUtils.randomAlphabetic(10)).put(attributeDef4, "2001-01-01").build(); val b = new AuthenticationResponse.Builder(); return b.id("_".concat(Random.nextHexRandom16())) .issuer(RandomStringUtils.randomAlphabetic(10)) .subject(RandomStringUtils.randomAlphabetic(10)) .statusCode("200") .inResponseTo("_".concat(Random.nextHexRandom16())) .subjectNameIdFormat("afaf") .levelOfAssurance(EaafConstants.EIDAS_LOA_PREFIX + RandomStringUtils.randomAlphabetic(5)) .attributes(attributeMap) .build(); } }