package at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.semper; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.junit.Assert.assertThat; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang3.RandomStringUtils; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.xml.ConfigurationException; import org.opensaml.xml.io.Unmarshaller; import org.opensaml.xml.io.UnmarshallerFactory; import org.opensaml.xml.io.UnmarshallingException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.w3c.dom.Element; import org.xml.sax.SAXException; import at.gv.egiz.eaaf.core.api.data.EAAFConfigConstants; import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; import at.gv.egiz.eaaf.core.impl.idp.conf.SPConfigurationImpl; import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; import at.gv.egovernment.moa.id.auth.modules.eIDAScentralAuth.EidasCentralAuthConstants; import at.gv.egovernment.moa.id.config.auth.OAAuthParameterDecorator; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "/SpringTest-context_basic_test.xml" }) @DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class AuthnRequestSemperProcessorTest { @Autowired DummyAuthConfigMap configMap; @Autowired AuthnRequestSemperProcessor processor; private MockHttpServletRequest httpReq; private MockHttpServletResponse httpResp; private TestRequestImpl pendingReq; /** * jUnit class initializer. * @throws ConfigurationException In case of an OpenSAML error * */ @BeforeClass public static void classInitializer() throws ConfigurationException { EAAFDefaultSAML2Bootstrap.bootstrap(); } /** * jUnit test set-up. * */ @Before public void initialize() { configMap.putConfigValue(EidasCentralAuthConstants.CONFIG_PROPS_SEMPER_MANDATES_ACTIVE, "true"); configMap.putConfigValue(EidasCentralAuthConstants.CONFIG_PROPS_SEMPER_MANDATES_MS_PROXY_LIST, RandomStringUtils.randomAlphabetic(15) + ",https://demo.egiz.gv.at/ms_connector/sp/metadata"); httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); httpResp = new MockHttpServletResponse(); RequestContextHolder.resetRequestAttributes(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); Map spConfig = new HashMap<>(); spConfig.put(EAAFConfigConstants.SERVICE_UNIQUEIDENTIFIER, "https://demo.egiz.gv.at/ms_connector/sp/metadata"); pendingReq = new TestRequestImpl(); pendingReq.setAuthURL("https://localhost/ms_connector"); pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); pendingReq.setSpConfig(new OAAuthParameterDecorator(new SPConfigurationImpl(spConfig, configMap))); } @Test public void semperModeNotSet() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { configMap.removeConfigValue(EidasCentralAuthConstants.CONFIG_PROPS_SEMPER_MANDATES_ACTIVE); AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_1.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void semperModeInactive() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { configMap.putConfigValue(EidasCentralAuthConstants.CONFIG_PROPS_SEMPER_MANDATES_ACTIVE, "false"); AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_1.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void allowedSPsNotSet() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { configMap.removeConfigValue(EidasCentralAuthConstants.CONFIG_PROPS_SEMPER_MANDATES_MS_PROXY_LIST); AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_1.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void nonValidSpEntityId() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { pendingReq.getServiceProviderConfiguration().getFullConfiguration().put( EAAFConfigConstants.SERVICE_UNIQUEIDENTIFIER, "https://apps.egiz.gv.at/ms_connector/sp/metadata"); AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_2.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void bPKTargetIsMissing_1() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_3.xml"); try { processor.process(httpReq, pendingReq, authReq , null); Assert.fail("No bPK target not detected"); } catch (AuthnRequestValidatorException e) { Assert.assertEquals("ErrorMessage", "pvp2.22", e.getErrorId()); } } @Test public void bPKTargetIsMissing_2() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_4.xml"); try { processor.process(httpReq, pendingReq, authReq , null); Assert.fail("No bPK target not detected"); } catch (AuthnRequestValidatorException e) { Assert.assertEquals("ErrorMessage", "pvp2.22", e.getErrorId()); } } @Test public void bPKTargetIsMissing_3() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_5.xml"); try { processor.process(httpReq, pendingReq, authReq , null); Assert.fail("No bPK target not detected"); } catch (AuthnRequestValidatorException e) { Assert.assertEquals("ErrorMessage", "pvp2.22", e.getErrorId()); } } @Test public void noRequestedAttributes() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_9.xml"); try { processor.process(httpReq, pendingReq, authReq , null); Assert.fail("No bPK target not detected"); } catch (AuthnRequestValidatorException e) { Assert.assertEquals("ErrorMessage", "pvp2.22", e.getErrorId()); } } @Test public void noSAML2ExtentsionElement() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_10.xml"); try { processor.process(httpReq, pendingReq, authReq , null); Assert.fail("No bPK target not detected"); } catch (AuthnRequestValidatorException e) { Assert.assertEquals("ErrorMessage", "pvp2.22", e.getErrorId()); } } @Test public void validSpEntityIdNoMandateProfiles() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_6.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNotNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertEquals("SP target not match", "urn:publicid:gv.at:eidasid+AT+EE", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void validSpEntityIdNotValidMandateProfiles_1() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_7.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNotNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertEquals("SP target not match", "urn:publicid:gv.at:eidasid+AT+EE", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void validSpEntityIdNotValidMandateProfiles_2() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_8.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNotNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertEquals("SP target not match", "urn:publicid:gv.at:eidasid+AT+EE", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertFalse("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNull("Mandate profiles", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); } @Test public void validSpEntityIdWithMandateProfiles() throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, AuthnRequestValidatorException { AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_1.xml"); processor.process(httpReq, pendingReq, authReq , null); ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); Assert.assertNotNull("SP config is null", spConfig); org.springframework.util.Assert.isInstanceOf(OAAuthParameterDecorator.class, spConfig, "SP config is NOT of type MOA-ID SP Config"); Assert.assertNotNull("SP target is null", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertEquals("SP target not match", "urn:publicid:gv.at:eidasid+AT+EE", spConfig.getAreaSpecificTargetIdentifier()); Assert.assertTrue("UseMandates flag", ((OAAuthParameterDecorator)spConfig).isShowMandateCheckBox()); Assert.assertNotNull("Mandate profiles are null", ((OAAuthParameterDecorator)spConfig).getMandateProfiles()); Assert.assertEquals("Number of mandate profiles not match", 3, ((OAAuthParameterDecorator)spConfig).getMandateProfiles().size()); assertThat("Mandate profiles not match", ((OAAuthParameterDecorator)spConfig).getMandateProfiles(), contains("Einzelvertretungsbefugnis", "1.2.40.0.10.1.7.3.1.1", "ERsB")); } private AuthnRequest getAuthRequest(String resource) throws ParserConfigurationException, SAXException, IOException, UnmarshallingException { final Element authBlockDom = DOMUtils.parseXmlValidating(AuthnRequestSemperProcessor.class.getResourceAsStream(resource)); final UnmarshallerFactory unmarshallerFactory = org.opensaml.xml.Configuration.getUnmarshallerFactory(); final Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(authBlockDom); return (AuthnRequest) unmarshaller.unmarshall(authBlockDom); } }