diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test')
5 files changed, 1901 insertions, 159 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java index 6adce26e..87073e81 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java @@ -3,6 +3,7 @@ package at.gv.egiz.eaaf.modules.pvp2.test.binding; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.util.Base64; import java.util.Map; @@ -13,23 +14,30 @@ import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory; 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.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.opensaml.core.config.InitializationException; import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.core.xml.io.Unmarshaller; import org.opensaml.core.xml.io.UnmarshallerFactory; @@ -40,6 +48,7 @@ import org.opensaml.messaging.encoder.MessageEncodingException; import org.opensaml.saml.common.SignableSAMLObject; import org.opensaml.saml.saml2.core.RequestAbstractType; import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -49,9 +58,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.net.URIComparator; import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) @@ -65,15 +76,27 @@ public class PostBindingTest { @Autowired private PostBinding bindingImpl; @Autowired private DummyCredentialProvider credentialProvider; @Autowired private DummyGuiBuilderConfigurationFactory guiBuilderFactory; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private IHttpClientFactory httpClientFactory; + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; protected MockHttpServletRequest httpReq; protected MockHttpServletResponse httpResp; protected IRequest pendingReq; + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ @BeforeClass - public static void classInitializer() throws InitializationException, ComponentInitializationException { + public static void classInitializer() throws Exception { EaafOpenSaml3xInitializer.eaafInitialize(); + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); } /** @@ -101,12 +124,14 @@ public class PostBindingTest { } @Test - public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { - final String serviceUrl = "http://testservice.org"; + public void decodeRequestWrongEndpoint() throws MessageDecodingException, SecurityException, + IOException, Pvp2MetadataException { + final String serviceUrl = "https://wrongEndpoint/pvp2/post"; - final IPvp2MetadataProvider metadataProvider = null; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); - final boolean isSpEndPoint = false; final URIComparator comparator = new EaafUriCompare(serviceUrl); final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( @@ -114,39 +139,169 @@ public class PostBindingTest { httpReq.setMethod("POST"); httpReq.addParameter("SAMLRequest", b64AuthnReq); + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Wrong http end-point not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); + Assert.assertNotNull("Parameters null", e.getParams()); + Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length); + + + } + + } + + @Test + public void decodeRequestMissingSignature() throws MessageDecodingException, SecurityException, + IOException, Pvp2MetadataException { + final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"))); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + + } + + @Test + public void decodeRequestWrongSignature() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception { + final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Invalid signature not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestMsgExpired() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { + final String serviceUrl = "https://eidas-test.bmi.gv.at/ms_connector/pvp/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_moaid_test.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = new String(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_withsig_expired.b64")), "UTF-8"); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Expired msg not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestSuccessMetadataReloadRequired() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final String b64AuthnReq = generateSaml2AuthnRequest( + credentialProvider.getIdpMetaDataSigningCredential()); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_wrong_sig.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_junit_keystore.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + null, "jUnit test", httpClientFactory.getHttpClient()); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); Assert.assertNotNull("PVP msg is null", msg); - Assert.assertNull("RelayState is not null", msg.getRelayState()); + Assert.assertNull("RelayState not null", msg.getRelayState()); Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } @Test - public void decodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException, - IOException, Pvp2Exception { + public void decodeRequestSuccessWithRelayStateRsaSig() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; final String relayState = RandomStringUtils.randomAlphanumeric(10); - final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( - PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); + final String b64AuthnReq = generateSaml2AuthnRequest( + credentialProvider.getIdpMetaDataSigningCredential()); httpReq.setMethod("POST"); httpReq.addParameter("SAMLRequest", b64AuthnReq); httpReq.addParameter("RelayState", relayState); - final IPvp2MetadataProvider metadataProvider = null; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); - final boolean isSpEndPoint = false; final URIComparator comparator = new EaafUriCompare(serviceUrl); - final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); Assert.assertNotNull("PVP msg is null", msg); Assert.assertNotNull("RelayState is not null", msg.getRelayState()); @@ -154,64 +309,63 @@ public class PostBindingTest { Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } @Test - public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { + public void decodeRequestSuccessWithoutRelayStateEcdsaSig() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; - final IPvp2MetadataProvider metadataProvider = null; - - final boolean isSpEndPoint = false; - final URIComparator comparator = new EaafUriCompare(serviceUrl); - - final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( - PostBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); + final String b64AuthnReq = generateSaml2AuthnRequest( + credentialProvider.getIdpAssertionSigningCredential()); httpReq.setMethod("POST"); httpReq.addParameter("SAMLRequest", b64AuthnReq); + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); Assert.assertNotNull("PVP msg is null", msg); Assert.assertNull("RelayState is not null", msg.getRelayState()); - Assert.assertNotNull("Response is null", msg.getInboundMessage()); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); - Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } @Test - public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { + public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; - final String relayState = RandomStringUtils.randomAlphanumeric(10); - final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( - PostBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); - httpReq.setMethod("POST"); - httpReq.addParameter("SAMLRequest", b64AuthnReq); - httpReq.addParameter("RelayState", relayState); + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); - final IPvp2MetadataProvider metadataProvider = null; - - final boolean isSpEndPoint = false; final URIComparator comparator = new EaafUriCompare(serviceUrl); + final String b64AuthnReq = generateSaml2Response(credentialProvider.getIdpMetaDataSigningCredential()); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); Assert.assertNotNull("PVP msg is null", msg); - Assert.assertNotNull("RelayState is not null", msg.getRelayState()); - Assert.assertEquals("RelayState not match", relayState, msg.getRelayState()); + Assert.assertNull("RelayState is not null", msg.getRelayState()); Assert.assertNotNull("Response is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); - Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } @@ -445,4 +599,48 @@ public class PostBindingTest { } + private String generateSaml2AuthnRequest(EaafX509Credential credentials) + throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException, + UnsupportedEncodingException { + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + + bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, + credentials, pendingReq); + + Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus()); + final String http = intHttpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ)); + return extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ); + + } + + private String generateSaml2Response(EaafX509Credential credentials) + throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException, + UnsupportedEncodingException { + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + response.setIssueInstant(DateTime.now()); + + bindingImpl.encodeResponse(intHttpReq, intHttpResp, response, "http://testservice.org", null, + credentials, pendingReq); + + Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus()); + final String http = intHttpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP)); + return extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP); + + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java index a99c8461..23cc98a6 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java @@ -6,15 +6,34 @@ import java.util.Base64; import javax.xml.parsers.ParserConfigurationException; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest; + import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; 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; @@ -22,6 +41,7 @@ import org.opensaml.messaging.decoder.MessageDecodingException; import org.opensaml.messaging.encoder.MessageEncodingException; import org.opensaml.saml.saml2.core.RequestAbstractType; import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -30,46 +50,57 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.xml.sax.SAXException; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; -import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; -import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; -import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; -import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; -import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.net.URISupport; import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) -@TestPropertySource(locations = {"/config/config_1.props"}) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) public class RedirectBindingTest { - public static final String HTTP_FORM_RELAYSTATE = "RelayState="; - public static final String HTTP_FORM_SAMLREQ = "SAMLRequest="; - public static final String HTTP_FORM_SAMLRESP = "SAMLResponse="; + public static final String HTTP_FORM_RELAYSTATE = "RelayState"; + public static final String HTTP_FORM_RELAYSTATE_PARAM = HTTP_FORM_RELAYSTATE + "="; + + public static final String HTTP_FORM_SAMLREQ = "SAMLRequest"; + public static final String HTTP_FORM_SAMLREQ_PARAM = HTTP_FORM_SAMLREQ + "="; + public static final String HTTP_FORM_SAMLRESP = "SAMLResponse"; + public static final String HTTP_FORM_SAMLRESP_PARM = HTTP_FORM_SAMLRESP + "="; + + public static final String HTTP_REDIRECT_SIGALG = "SigAlg"; + public static final String HTTP_REDIRECT_SIGALG_PARAM = HTTP_REDIRECT_SIGALG + "="; + public static final String HTTP_REDIRECT_SIGNATURE = "Signature"; + public static final String HTTP_REDIRECT_SIGNATURE_PARAM = HTTP_REDIRECT_SIGNATURE + "="; - public static final String HTTP_REDIRECT_SIGALG = "SigAlg="; - public static final String HTTP_REDIRECT_SIGNATURE = "Signature="; + @Autowired + private RedirectBinding bindingImpl; + @Autowired + private DummyCredentialProvider credentialProvider; + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private IHttpClientFactory httpClientFactory; - @Autowired private RedirectBinding bindingImpl; - @Autowired private DummyCredentialProvider credentialProvider; - @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; protected MockHttpServletRequest httpReq; protected MockHttpServletResponse httpResp; protected IRequest pendingReq; + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ @BeforeClass - public static void classInitializer() throws InitializationException, ComponentInitializationException { + public static void classInitializer() throws Exception { EaafOpenSaml3xInitializer.eaafInitialize(); + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); } /** @@ -97,34 +128,236 @@ public class RedirectBindingTest { } @Test - public void decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { + public void decodeRequestNoSignature() throws MessageDecodingException, + SecurityException, IOException, Pvp2MetadataException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + + } + + @Test + public void decodeRequestWrongEndpoint() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception { + final String serviceUrl = "http://wrongEndPoint.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Wrong signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + Assert.assertNotNull("Parameters null", e.getParams()); + Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestWrongSignature() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Wrong signature not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestExpired() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; - - final IPvp2MetadataProvider metadataProvider = + + final IPvp2MetadataProvider metadataProvider = metadataResolverFactory.createMetadataProvider( - "classpath:/data/metadata_1.xml", null, "jUnit metadata resolver", null); + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); - final boolean isSpEndPoint = false; final URIComparator comparator = new EaafUriCompare(serviceUrl); httpReq.setMethod("GET"); httpReq.setRequestURI("http://testservice.org"); - httpReq.setParameter("SAMLRequest","nVRNb9swDD13wP6DoXvkr/RjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw++SdQj+fhIanF7qKXXgrFCq4SENCAeqFwXQlUJ+fZ0N7sht+nC8lpGO5Y1+KIe4XcDFj3nqCw7vSSkMYppboVlitdgGeZsk32+ZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp/Qxy/lcsuFMeO8Qvijvk+Ops9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx/E+z4o5OohvR6sczZjId7XgQ/VE+9Om5rj+/CjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp+PR6krofyFP2Y68N4025+Q4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc/U+s3AIpuH9ygIhwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1+00i2Fxne77ecCxRuor1l2Dy1Ifz6o/6/so+78p+b0/Dz+GdI/"); - httpReq.setParameter("SigAlg","http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); - httpReq.setParameter("Signature","DOVMqh17xn4wl+yvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r+YbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI869U+H6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu/+nMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6RjgzvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD/Ia0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3XhcNRQ3+cpAf65zHGMBAv1aRy7Bmv0++OvCavufykqI2EHtg=="); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkj2RFJsQujAQFAnTD1nQ97FIoNu1qkyVPop20v36KYwcusPVgQ" + + "AeLeiQfH0mvbo6V9FowVmgVk5AGxAOV6VyoMiY%2FHm5nS3KTrCyvZFSztMFndQ9%2FGrDoOUdl2fklJo1RTHMrLFO8AsswY7v" + + "0yx2LaMBqo1FnWhIvtRYMulRrrWxTgdmBaUUGW5XD0aV3CEQj9g3CGeFovIU4fhuXXSiOHeNnxJr5PjqbPQOpNiXxtpuYPHGAf" + + "cFhnsH1MixgnucZL6JwzhdREYT53MGsbVxoi1xhTKIgCmZBNAsWD8Fn5s6na7qMwp%2FEexwUcvWQXg%2FWOZuxEO%2FrwIfqi" + + "XerTcXxffjJIvJZ0UEZKBT4QpJTwdZVnEOlKZTilZYt5djda22Qy6fTp9SlUP7KHzMdeO%2Ba%2FS%2FIcArx5OOHq6s%2BzFe" + + "H226mEep9XbTB0pO6zNoZ8U1Lkb14qZT6sDbAEWKCpoEpCtanHlp0QpIpw%2BtfqPUbAHm3D25QEY6T9mGs5jjWWjrF76GY1KF" + + "%2BIw6HA7WozW9a6pZC47vd9jOB4hXU9zS9gxakvxjU%2F1f2UXf%2BU3NyeR7%2FGZK%2F&SigAlg=http%3A%2F%2Fwww.w3" + + ".org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=JogFpk2oimCnBCgE7eZx%2B6yoJu2ZCgus5vM1opkTk" + + "OLM9qgNMUJJJbIeA3j2TR%2BWx3pUApnV7ed9CuTBF94b3ELkFdaZAetfLzY8gnPLCBmcYIYkwg3bK7ZQWEBJpjNoU%2BaBHXV" + + "OgptLUt0qRWavm%2BiPOUXRWpb0PtgvApTieRk32gBfZbuPOltWjrRCKaa2ulKBjB34LqYdAaIWaVix2sGvg128p6lC7bQ%2Fz" + + "wmz6j8S5Vn8snvlg48MlBldTWKSZrUERx3MwTyaB17A617XmX2QKo8fGCQ6O7FF4umFyWGAlujI%2FwqafTfPlaNX2usHynHS6" + + "XkH5HWCDSAe3%2BVR1w%3D%3D "); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Expired message not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, + "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + @Test + public void decodeRequestSuccess() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString(generateAuthnRequest(credentialProvider.getIdpMetaDataSigningCredential())); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); Assert.assertNotNull("PVP msg is null", msg); Assert.assertNull("RelayState is not null", msg.getRelayState()); Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); - Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } @@ -143,88 +376,123 @@ public class RedirectBindingTest { final IPvp2MetadataProvider metadataProvider = null; - final boolean isSpEndPoint = false; final URIComparator comparator = new EaafUriCompare(serviceUrl); - final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); Assert.assertNotNull("PVP msg is null", msg); Assert.assertNotNull("RelayState is not null", msg.getRelayState()); Assert.assertEquals("RelayState not match", relayState, msg.getRelayState()); Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); - Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); } - @Ignore @Test - public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { + public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, + Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; - final IPvp2MetadataProvider metadataProvider = null; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); - final boolean isSpEndPoint = false; final URIComparator comparator = new EaafUriCompare(serviceUrl); - final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( - RedirectBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); - httpReq.setMethod("POST"); - httpReq.addParameter("SAMLRequest", b64AuthnReq); + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString(generateResponse(credentialProvider.getIdpMetaDataSigningCredential())); + httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); Assert.assertNotNull("PVP msg is null", msg); Assert.assertNull("RelayState is not null", msg.getRelayState()); Assert.assertNotNull("Response is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); - Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } - @Ignore @Test - public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, - IOException, Pvp2Exception { + public void decodeResponseSuccessWithRelayStateAndMetadataReload() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException { final String serviceUrl = "http://testservice.org"; final String relayState = RandomStringUtils.randomAlphanumeric(10); - final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( - RedirectBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); - httpReq.setMethod("POST"); - httpReq.addParameter("SAMLRequest", b64AuthnReq); - httpReq.addParameter("RelayState", relayState); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_wrong_sig.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); - final IPvp2MetadataProvider metadataProvider = null; + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_junit_keystore.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); - final boolean isSpEndPoint = false; - final URIComparator comparator = new EaafUriCompare(serviceUrl); + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + null, "jUnit test", httpClientFactory.getHttpClient()); + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setParameter(HTTP_FORM_RELAYSTATE, relayState); + httpReq.setQueryString(generateResponse(credentialProvider.getIdpMetaDataSigningCredential())); + + httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + final InboundMessageInterface msg = - bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, comparator); + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); Assert.assertNotNull("PVP msg is null", msg); - Assert.assertNotNull("RelayState is not null", msg.getRelayState()); + Assert.assertNotNull("RelayState is null", msg.getRelayState()); Assert.assertEquals("RelayState not match", relayState, msg.getRelayState()); Assert.assertNotNull("Response is null", msg.getInboundMessage()); Assert.assertNotNull("EntityId is null", msg.getEntityID()); - Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID()); - Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); } @Test public void encodeRequestSuccess() throws MessageDecodingException, SecurityException, MessageEncodingException, XMLParserException, UnmarshallingException, - CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { - //build test data + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + // build test data final String serviceUrl = "http://testservice.org"; final String relayState = null; final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( @@ -234,7 +502,7 @@ public class RedirectBindingTest { bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - //validate + // validate Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -246,33 +514,33 @@ public class RedirectBindingTest { Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); Assert.assertTrue("Wrong redirect URL", - locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ)); + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); - final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true); Assert.assertNotNull("Saml msg is null", respSamlMsg); Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); - final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true); + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); Assert.assertNotNull("SigAlg is null", sigAlg); Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, URLDecoder.decode(sigAlg, "UTF-8")); - final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true); + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); Assert.assertNotNull("Saml signature null", samlSig); Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); - final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); Assert.assertNull("RelayState parameter", respRelayState); } - @Test public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException, MessageEncodingException, XMLParserException, UnmarshallingException, - CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { - //build test data + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + // build test data final String serviceUrl = "http://testservice.org"; final String relayState = null; final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( @@ -282,8 +550,8 @@ public class RedirectBindingTest { bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, credentialProvider.getIdpAssertionSigningCredential(), pendingReq); - //validate - //validate + // validate + // validate Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -295,34 +563,34 @@ public class RedirectBindingTest { Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); Assert.assertTrue("Wrong redirect URL", - locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ)); + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); - final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true); Assert.assertNotNull("Saml msg is null", respSamlMsg); Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); - final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true); + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); Assert.assertNotNull("SigAlg is null", sigAlg); Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_EC, URLDecoder.decode(sigAlg, "UTF-8")); - final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true); + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); Assert.assertNotNull("Saml signature null", samlSig); Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); - final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); Assert.assertNull("RelayState parameter", respRelayState); - } @Test public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException, MessageEncodingException, XMLParserException, UnmarshallingException, - CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { - //build test data + // build test data final String serviceUrl = "http://testservice.org"; final String relayState = RandomStringUtils.randomAlphabetic(10); final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( @@ -332,8 +600,7 @@ public class RedirectBindingTest { bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - - //validate + // validate Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -345,36 +612,36 @@ public class RedirectBindingTest { Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); Assert.assertTrue("Wrong redirect URL", - locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ)); + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); - final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true); Assert.assertNotNull("Saml msg is null", respSamlMsg); Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); - final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true); + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); Assert.assertNotNull("SigAlg is null", sigAlg); Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, URLDecoder.decode(sigAlg, "UTF-8")); - final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true); + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); Assert.assertNotNull("Saml signature null", samlSig); Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); - final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); Assert.assertNotNull("RelayState parameter", respRelayState); Assert.assertEquals("RelayState not match", relayState, URLDecoder.decode(respRelayState, "UTF-8")); - } @Test public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, MessageEncodingException, XMLParserException, UnmarshallingException, - CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { - //build test data + // build test data final String serviceUrl = "http://testservice.org"; final String relayState = RandomStringUtils.randomAlphabetic(10); final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( @@ -384,8 +651,7 @@ public class RedirectBindingTest { bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState, credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - - //validate + // validate Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -397,23 +663,23 @@ public class RedirectBindingTest { Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); Assert.assertTrue("Wrong redirect URL", - locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP)); + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM)); - final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true); + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, true); Assert.assertNotNull("Saml msg is null", respSamlMsg); Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); - final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true); + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); Assert.assertNotNull("SigAlg is null", sigAlg); Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, URLDecoder.decode(sigAlg, "UTF-8")); - final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true); + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); Assert.assertNotNull("Saml signature null", samlSig); Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); - final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); Assert.assertNotNull("RelayState parameter", respRelayState); Assert.assertEquals("RelayState not match", relayState, URLDecoder.decode(respRelayState, "UTF-8")); @@ -423,9 +689,10 @@ public class RedirectBindingTest { @Test public void encodeResponseSuccess() throws MessageDecodingException, SecurityException, MessageEncodingException, XMLParserException, UnmarshallingException, - CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { - //build test data + // build test data final String serviceUrl = "http://testservice.org"; final String relayState = null; final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( @@ -435,8 +702,7 @@ public class RedirectBindingTest { bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState, credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); - - //validate + // validate Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); @@ -448,23 +714,23 @@ public class RedirectBindingTest { Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); Assert.assertTrue("Wrong redirect URL", - locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP)); + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM)); - final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true); + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, true); Assert.assertNotNull("Saml msg is null", respSamlMsg); Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); - final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, true); + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); Assert.assertNotNull("SigAlg is null", sigAlg); Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, URLDecoder.decode(sigAlg, "UTF-8")); - final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE, true); + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); Assert.assertNotNull("Saml signature null", samlSig); Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); - final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, false); + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); Assert.assertNull("RelayState parameter", respRelayState); } @@ -490,4 +756,45 @@ public class RedirectBindingTest { } + private String generateAuthnRequest(EaafX509Credential credential) throws Pvp2Exception, + XMLParserException, UnmarshallingException { + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + + bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, + credential, pendingReq); + + Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus()); + final String locationHeader = intHttpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + return locationHeader.split("\\?")[1]; + + } + + private String generateResponse(EaafX509Credential credential) throws Pvp2Exception, + XMLParserException, UnmarshallingException { + new MockHttpServletRequest(); + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + + final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + + bindingImpl.encodeResponse(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, + credential, pendingReq); + + Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus()); + final String locationHeader = intHttpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + return locationHeader.split("\\?")[1]; + + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java new file mode 100644 index 00000000..1125d30e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java @@ -0,0 +1,214 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.Marshaller; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.soap.soap11.Envelope; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import net.shibboleth.utilities.java.support.logic.Constraint; +import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource(locations = {"/config/config_1.props"}) +public class SoapBindingTest { + + @Autowired private SoapBinding bindingImpl; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private DummyCredentialProvider credentialProvider; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + protected IRequest pendingReq; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new TestRequestImpl(); + + } + + @Test + public void withoutSig() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException { + final String serviceUrl = "https://localhost/pvp2/post"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + payload.setIssueInstant(DateTime.now()); + final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload); + final Marshaller marshaller = Constraint.isNotNull( + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), + "SOAP Envelope marshaller not available"); + final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); + SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); + httpReq.setMethod("POST"); + httpReq.setContentType("text/xml"); + httpReq.setContent(arrayOut.toByteArray()); + + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, + SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + } + + @Test + public void wrongSignature() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException { + final String serviceUrl = "https://localhost/pvp2/post"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")); + payload.setIssueInstant(DateTime.now()); + final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload); + final Marshaller marshaller = Constraint.isNotNull( + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), + "SOAP Envelope marshaller not available"); + final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); + SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); + httpReq.setMethod("POST"); + httpReq.setContentType("text/xml"); + httpReq.setContent(arrayOut.toByteArray()); + + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, + SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + + } + } + + @Test + public void validSignature() throws Pvp2Exception, MarshallingException, XMLParserException, + UnmarshallingException, CredentialsNotAvailableException { + final String serviceUrl = "https://localhost/pvp2/post"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")); + payload.setIssueInstant(DateTime.now()); + final RequestAbstractType signedPayload = Saml2Utils.signSamlObject( + payload, credentialProvider.getIdpMetaDataSigningCredential(), true); + + final Envelope enveloped = Saml2Utils.buildSoap11Envelope(signedPayload); + final Marshaller marshaller = Constraint.isNotNull( + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), + "SOAP Envelope marshaller not available"); + final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); + SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); + httpReq.setMethod("POST"); + httpReq.setContentType("text/xml"); + httpReq.setContent(arrayOut.toByteArray()); + + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, + SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("Inbound msg is null", msg); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void encodeResponse() throws XMLParserException, UnmarshallingException, + Pvp2Exception, CredentialsNotAvailableException, UnsupportedEncodingException { + final String serviceUrl = "http://testservice.org"; + + final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + + bindingImpl.encodeResponse(httpReq, httpResp, response, serviceUrl, null, + credentialProvider.getIdpMetaDataSigningCredential(), pendingReq); + + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/xml", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java new file mode 100644 index 00000000..2d46f102 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java @@ -0,0 +1,298 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.SecurityException; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + + + + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class MetadataBuilderTest { + + @Autowired private PvpMetadataBuilder metadataBuilder; + @Autowired private DummyCredentialProvider credentialProvider; + + private static CertificateFactory fact; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + fact = CertificateFactory.getInstance("X.509"); + } + + @Test + public void buildIdpMetadata() throws CredentialsNotAvailableException, EaafException, + SecurityException, TransformerFactoryConfigurationError, MarshallingException, + TransformerException, ParserConfigurationException, IOException, SignatureException, + XMLParserException, UnmarshallingException, CertificateException { + + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(false, true); + + //generate metadata + final String metadata = metadataBuilder.buildPvpMetadata(config); + + //validate + final EntityDescriptor entity = validateMetadata(metadata); + Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); + Assert.assertNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + + } + + @Test + public void buildSpMetadata() throws CredentialsNotAvailableException, EaafException, + SecurityException, TransformerFactoryConfigurationError, MarshallingException, + TransformerException, ParserConfigurationException, IOException, SignatureException, + XMLParserException, UnmarshallingException, CertificateException { + + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(true, false); + + //generate metadata + final String metadata = metadataBuilder.buildPvpMetadata(config); + + //validate + final EntityDescriptor entity = validateMetadata(metadata); + Assert.assertNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); + Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + + } + + @Test + public void buildSpAndIdpMetadata() throws CredentialsNotAvailableException, EaafException, + SecurityException, TransformerFactoryConfigurationError, MarshallingException, + TransformerException, ParserConfigurationException, IOException, SignatureException, + XMLParserException, UnmarshallingException, CertificateException { + + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(true, true); + + //generate metadata + final String metadata = metadataBuilder.buildPvpMetadata(config); + + //validate + final EntityDescriptor entity = validateMetadata(metadata); + Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); + Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + + } + + private EntityDescriptor validateMetadata(String metadata) throws UnsupportedEncodingException, + XMLParserException, UnmarshallingException, SignatureException, CertificateException { + Assert.assertNotNull("Metadata is null", metadata); + Assert.assertFalse("Metadata is empty", metadata.isEmpty()); + + final EntityDescriptor entity = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + new ByteArrayInputStream(metadata.getBytes("UTF-8"))); + + Assert.assertNotNull("Unmarshalling failed", entity); + Assert.assertNotNull("EntityId is null", entity.getEntityID()); + + Assert.assertNotNull("Signature is null", entity.getSignature()); + final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); + sigValidator.validate(entity.getSignature()); + + final Credential cred = new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))); + SignatureValidator.validate(entity.getSignature(), cred); + + return entity; + } + + private IPvpMetadataBuilderConfiguration idpMetadataConfig(boolean buildSpInfos, boolean buildIdpInfos) { + return new IPvpMetadataBuilderConfiguration() { + + @Override + public boolean wantAuthnRequestSigned() { + return true; + } + + @Override + public boolean wantAssertionSigned() { + return true; + } + + @Override + public String getSpSloSoapBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getSpSloRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getSpSloPostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public Collection<RequestedAttribute> getSpRequiredAttributes() { + return null; + } + + @Override + public String getSpNameForLogging() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getSpAssertionConsumerServiceRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getSpAssertionConsumerServicePostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public List<String> getSpAllowedNameIdTypes() { + return Arrays.asList(NameIDType.PERSISTENT); + } + + @Override + public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIdpAssertionSigningCredential(); + } + + @Override + public Organization getOrgansiationInformation() { + return null; + } + + @Override + public int getMetadataValidUntil() { + return 10; + } + + @Override + public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIdpMetaDataSigningCredential(); + } + + @Override + public String getIdpWebSsoRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getIdpWebSsoPostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getIdpSloRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getIdpSloPostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public List<String> getIdpPossibleNameIdTypes() { + return Arrays.asList(NameIDType.PERSISTENT); + } + + @Override + public List<Attribute> getIdpPossibleAttributes() { + return null; + } + + @Override + public String getEntityID() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getEntityFriendlyName() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIdpAssertionSigningCredential(); + } + + @Override + public List<ContactPerson> getContactPersonInformation() { + return null; + } + + @Override + public boolean buildSpSsoDescriptor() { + return buildSpInfos; + } + + @Override + public boolean buildIdpSsoDescriptor() { + return buildIdpInfos; + } + + @Override + public boolean buildEntitiesDescriptorAsRootElement() { + return false; + } + }; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java new file mode 100644 index 00000000..f40fbc74 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java @@ -0,0 +1,725 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.transform.TransformerException; + +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PvpEntityCategoryFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.io.IOUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; +import org.opensaml.saml.metadata.resolver.filter.impl.RequiredValidUntilFilter; +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider; +import org.opensaml.xmlsec.signature.support.SignatureValidationParametersCriterion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class MetadataResolverTest { + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; + + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired + private IHttpClientFactory httpClientFactory; + @Autowired private DummyCredentialProvider credentialProvider; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); + + } + + /** + * Single test initializer. + * + */ + @Before + public void testInitializer() { + + } + + @Test + public void wrongSchema() { + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_schema.xml", + filterChain, "jUnit test", null); + Assert.fail("Wrong XML Schema not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong ErrorCode", "internal.pvp.08", e.getErrorId()); + Assert.assertNotNull("params null", e.getParams()); + Assert.assertEquals("Params size", 2, e.getParams().length); + Assert.assertEquals("Param[0] wrong", + "classpath:/data/pvp_metadata_wrong_schema.xml", e.getParams()[0]); + + } + + } + + @Test + public void simpleClasspathMetadataWithoutSigValidation() + throws Pvp2MetadataException, ComponentInitializationException, ResolverException, + Pvp2InternalErrorException { + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", + filterChain, "jUnit test", null); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/demoportal_demologin/"); + Assert.assertNotNull("No EntityDescripter", entityId); + + Assert.assertNotNull("Metadata provider is null", mdResolver); + final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver); + + final CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new EntityIdCriterion("https://demo.egiz.gv.at/demoportal_demologin/")); + criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); + final SignatureValidationParameters sigValCrit = new SignatureValidationParameters(); + sigValCrit.setBlacklistedAlgorithms( + ConfigurationService.get(SignatureValidationConfiguration.class) + .getBlacklistedAlgorithms()); + sigValCrit.setSignatureTrustEngine( + TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver)); + criteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit)); + + final Iterable<Credential> keyInfos = resolver.resolve(criteriaSet); + Assert.assertNotNull("KeyInfos null", keyInfos); + + } + + @Test + public void noCredentials() { + final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", null); + Assert.fail("Untrusted signature not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + + } + + } + + @Test + public void wrongCredentials() throws CertificateException { + final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + final BasicX509Credential credential = new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))); + credentials.add(credential); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", null); + Assert.fail("Untrusted signature not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + + } + + } + + @Test + public void validCredentialsInvalidSig() throws CertificateException, Pvp2MetadataException, + ResolverException { + final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + try { + metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", null); + Assert.fail("Untrusted signature not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + + } + + } + + @Test + public void metadataSignatureValidCredentials() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final String metadataUrl = "classpath:/data/pvp_metadata_valid.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + filterList.add(new PvpEntityCategoryFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata"); + Assert.assertNotNull("No EntityDescripter", entityIdNotExists); + + } + + @Test + public void metadataSignatureValidCredentialsSecond() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory.xml")); + metadata.setValidUntil(DateTime.now().plusDays(1)); + metadata.setSignature(null); + Saml2Utils.signSamlObject(metadata, credentialProvider.getIdpMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(metadata); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new PvpEntityCategoryFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + + + final EntityDescriptor descr = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata"); + Assert.assertNotNull("No EntityDescripter", descr); + + final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS) + .getAttributeConsumingServices().get(0).getRequestAttributes(); + Assert.assertNotNull("Req. attributes are null", reqAttr); + Assert.assertEquals("# of req. attributes", 20, reqAttr.size()); + + } + + @Test + public void metadataSignatureValidCredentialsThird() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory_egov.xml")); + metadata.setValidUntil(DateTime.now().plusDays(1)); + metadata.setSignature(null); + Saml2Utils.signSamlObject(metadata, credentialProvider.getIdpMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(metadata); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new PvpEntityCategoryFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + + + final EntityDescriptor descr = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata"); + Assert.assertNotNull("No EntityDescripter", descr); + + final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS) + .getAttributeConsumingServices().get(0).getRequestAttributes(); + Assert.assertNotNull("Req. attributes are null", reqAttr); + Assert.assertEquals("# of req. attributes", 9, reqAttr.size()); + + } + + @Test + public void metadataExpired() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid.xml")); + metadata.setValidUntil(DateTime.now().minusDays(2)); + metadata.setSignature(null); + Saml2Utils.signSamlObject(metadata, credentialProvider.getIdpMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(metadata); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new RequiredValidUntilFilter()); + filterList.add(new PvpEntityCategoryFilter(false)); + + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + Assert.fail("Expired metadata not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + + } + + + } + + @Test + public void simpleClasspathMetadataWithoutSigValidationMoaidTwoSigKeys() + throws Pvp2MetadataException, ComponentInitializationException, ResolverException, + Pvp2InternalErrorException { + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_moaid_test.xml", + filterChain, "jUnit test", null); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + Assert.assertNotNull("Metadata provider is null", mdResolver); + final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver); + + final CriteriaSet sigCriteriaSet = new CriteriaSet(); + sigCriteriaSet.add(new EntityIdCriterion(entityIdToResolve)); + sigCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + sigCriteriaSet.add(new UsageCriterion(UsageType.SIGNING)); + final SignatureValidationParameters sigValCrit = new SignatureValidationParameters(); + sigValCrit.setBlacklistedAlgorithms( + ConfigurationService.get(SignatureValidationConfiguration.class) + .getBlacklistedAlgorithms()); + sigValCrit.setSignatureTrustEngine( + TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver)); + sigCriteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit)); + + final Iterable<Credential> singingKeyInfos = resolver.resolve(sigCriteriaSet); + Assert.assertNotNull("Signing KeyInfos null", singingKeyInfos); + Assert.assertTrue("First Credential resolved", singingKeyInfos.iterator().hasNext()); + Assert.assertTrue("Second Credential resolved", singingKeyInfos.iterator().hasNext()); + + final CriteriaSet encCriteriaSet = new CriteriaSet(); + encCriteriaSet.add(new EntityIdCriterion(entityIdToResolve)); + encCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + encCriteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); + final Iterable<Credential> encKeyInfos = resolver.resolve(encCriteriaSet); + Assert.assertNotNull("Encryption KeyInfos null", encKeyInfos); + Assert.assertTrue("No Credential resolved", encKeyInfos.iterator().hasNext()); + + } + + @Test + public void httpMetadataLoading() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + } + + @Test + public void httpMetadataLoadingRefeshFailed() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + final DateTime lastRefreshSucess = mdResolver.getLastSuccessfulRefresh(); + + try { + mdResolver.refresh(); + Assert.fail("Refesh possible without available metadata"); + + } catch (final ResolverException e) { + Assert.assertFalse("Wrong Refesh success flag", mdResolver.wasLastRefreshSuccess()); + Assert.assertEquals("Wrong refresh success date", lastRefreshSucess, mdResolver + .getLastSuccessfulRefresh()); + + } + + } + + @Test + public void httpMetadataLoadingWithRefeshSuccess() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + final DateTime lastRefresh = mdResolver.getLastRefresh(); + + // refresh metadata + mdResolver.refresh(); + + Assert.assertTrue("Refresh not sucessful", mdResolver.wasLastRefreshSuccess()); + Assert.assertTrue("Wrong last refresh date", lastRefresh.isBefore(mdResolver.getLastRefresh())); + + } + + @Test + public void httpMetadataLoadingWithoutHttpClient() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", null); + Assert.fail("No httpclient not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong params size", 2, e.getParams().length); + + } + } + + @Test + public void httpMetadataLoadingWrongUrl() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + "http://127.0.0.1/notexist", + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + Assert.fail("No httpclient not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong params size", 2, e.getParams().length); + + } + + } + + private MetadataCredentialResolver createKeyInfoResolver(IPvp2MetadataProvider mdResolver) + throws ComponentInitializationException { + final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); + keyInfoProvider.add(new DSAKeyValueProvider()); + keyInfoProvider.add(new RSAKeyValueProvider()); + keyInfoProvider.add(new InlineX509DataProvider()); + final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( + keyInfoProvider); + + final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( + mdResolver); + roleDescriptorResolver.setRequireValidMetadata(true); + roleDescriptorResolver.initialize(); + + final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); + resolver.setRoleDescriptorResolver(roleDescriptorResolver); + resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); + resolver.initialize(); + + return resolver; + } +} |