[java-plugin-shibd] branch main updated: More unit tests, add support for parsing encoded message to check.
Scott Cantor
cantor.2 at osu.edu
Tue Jul 30 15:08:01 UTC 2024
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-plugin-shibd.
View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd.git;a=commit;h=ab48946c2e43ee8ddab65cf2ee1288878ad2100a
The following commit(s) were added to refs/heads/main by this push:
new ab48946 More unit tests, add support for parsing encoded message to check.
ab48946 is described below
commit ab48946c2e43ee8ddab65cf2ee1288878ad2100a
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jul 30 11:07:58 2024 -0400
More unit tests, add support for parsing encoded message to check.
---
.../shibboleth/sp/flows/AbstractSPFlowTest.java | 59 ++++++++++++++++++
.../flows/saml2/SAML2SessionInitiatorFlowTest.java | 57 ++++++++++++++++-
.../idp/module/conf/sp/metadata-providers.xml | 71 +++++++++++++++++-----
.../shibboleth/idp/module/conf/sp/test-agents.xml | 4 ++
.../saml/saml2/profile/impl/AddAuthnRequest.java | 2 +
.../sp/profile/AbstractAgentRequestAction.java | 24 ++++++--
.../shibboleth/sp/profile/impl/EncodeMessage.java | 3 +-
7 files changed, 198 insertions(+), 22 deletions(-)
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
index d95d702..dd0e00a 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/AbstractSPFlowTest.java
@@ -19,13 +19,20 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
+import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.codec.binary.Base64;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.decoder.MessageDecodingException;
import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
@@ -35,7 +42,12 @@ import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import net.shibboleth.idp.test.flows.AbstractFlowTest;
+import net.shibboleth.shared.collection.Pair;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.net.URISupport;
+import net.shibboleth.shared.primitive.NonnullSupplier;
import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
+import net.shibboleth.shared.xml.ParserPool;
import net.shibboleth.sp.context.AgentRequestContext;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.profile.impl.ResolveApplication;
@@ -68,6 +80,10 @@ public abstract class AbstractSPFlowTest extends AbstractFlowTest {
protected String flowId;
protected String endStateId;
+
+ @Autowired
+ @Qualifier("shibboleth.ParserPool")
+ protected ParserPool parserPool;
protected AbstractSPFlowTest(final String id) {
this(id, END_STATE_ID);
@@ -192,4 +208,47 @@ public abstract class AbstractSPFlowTest extends AbstractFlowTest {
}
}
+ /**
+ * Decodes the SAML message encoded via HTTP-Redirect binding.
+ *
+ * @param url the encoded redirect
+ *
+ * @return decoded message
+ * @throws MessageDecodingException
+ */
+ @Nonnull protected SAMLObject decodeRedirect(@Nullable final String url) throws MessageDecodingException {
+ final MockHttpServletRequest mock = new MockHttpServletRequest("GET", "url");
+ final int index = url != null ? url.indexOf('?') : -1;
+ if (url == null || index < 0) {
+ throw new MessageDecodingException("No query string");
+ }
+ final List<Pair<String,String>> params = URISupport.parseQueryString(url.substring(index + 1));
+ for (final var param : params) {
+ final String name = param.getFirst();
+ if (name != null) {
+ mock.addParameter(name, param.getSecond());
+ }
+ }
+
+ final HTTPRedirectDeflateDecoder decoder = new HTTPRedirectDeflateDecoder();
+ decoder.setHttpServletRequestSupplier(NonnullSupplier.of(mock));
+ decoder.setParserPool(parserPool);
+
+ try {
+ decoder.initialize();
+ } catch (final ComponentInitializationException e) {
+ throw new MessageDecodingException(e);
+ }
+
+ decoder.decode();
+
+ final MessageContext mc = decoder.getMessageContext();
+ decoder.destroy();
+
+ if (mc != null && mc.getMessage() instanceof SAMLObject saml) {
+ return saml;
+ }
+ throw new MessageDecodingException("No message, or incorrect type.");
+ }
+
}
\ No newline at end of file
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/saml2/SAML2SessionInitiatorFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/saml2/SAML2SessionInitiatorFlowTest.java
index 2779f3f..465fff0 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/saml2/SAML2SessionInitiatorFlowTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/saml2/SAML2SessionInitiatorFlowTest.java
@@ -15,9 +15,15 @@
package net.shibboleth.sp.flows.saml2;
import java.io.IOException;
+import java.nio.charset.Charset;
+import java.time.Instant;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.saml2.core.AuthnRequest;
import org.springframework.webflow.executor.FlowExecutionResult;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -25,6 +31,7 @@ import org.testng.annotations.Test;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.flows.AbstractSPFlowTest;
+import net.shibboleth.sp.messaging.RemotedHttpServletResponse;
/**
* Unit test for the SP session-initiator flow.
@@ -70,13 +77,30 @@ public class SAML2SessionInitiatorFlowTest extends AbstractSPFlowTest {
assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
}
+ /**
+ * Test flow with no valid endpoint
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testNoEndpoint() throws IOException {
+ setDefaultAuth();
+ setApplicationRequest("no-endpoint");
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
+ }
+
/**
* Test basic use of flow.
*
* @throws IOException
+ * @throws MessageDecodingException
*/
@Test
- public void testSimple() throws IOException {
+ public void testRedirect() throws IOException, MessageDecodingException {
setDefaultAuth();
setApplicationRequest(APPLICATION_ID);
@@ -85,8 +109,37 @@ public class SAML2SessionInitiatorFlowTest extends AbstractSPFlowTest {
assertFlowExecutionOutcome(result.getOutcome());
final DDF output = assertOutputMessageEvent(result, null);
+ assertOutputMessage(output);
+ }
+
+ /**
+ * Decode an encoded response and run sanity checks against it.
+ *
+ * @param output the wrapped output message from the flow
+ *
+ * @throws MessageDecodingException
+ */
+ private void assertOutputMessage(@Nullable final DDF output) throws MessageDecodingException {
assert output != null;
Assert.assertTrue(output.isstruct());
+ final DDF http = output.getmember("http");
+ Assert.assertTrue(http.isstruct());
+
+ final AuthnRequest authnRequest;
+ final String redirect = http.getmember("redirect").string();
+ if (redirect != null) {
+ final SAMLObject saml = decodeRedirect(redirect);
+ assert saml instanceof AuthnRequest;
+ authnRequest = (AuthnRequest) saml;
+ Assert.assertTrue(redirect.startsWith(authnRequest.getDestination()));
+ } else {
+ // TODO POST
+ authnRequest = null;
+ }
+
+ assert authnRequest != null;
+ Assert.assertNotNull(authnRequest.getID());
+ Assert.assertTrue(Instant.now().isAfter(authnRequest.getIssueInstant()));
}
-
+
}
\ No newline at end of file
diff --git a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/metadata-providers.xml b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/metadata-providers.xml
index c0b438e..ba3bf0f 100644
--- a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/metadata-providers.xml
+++ b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/metadata-providers.xml
@@ -27,12 +27,13 @@
<!-- Example metadata provider. -->
<MetadataProvider id="InlineExample" xsi:type="InlineMetadataProvider" indexesRef="testbed.MetadataIndexes">
- <md:EntityDescriptor ID="entity" entityID="https://idp.example.org">
- <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
- <md:KeyDescriptor>
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
+ <md:EntitiesDescriptor Name="tests">
+ <md:EntityDescriptor entityID="https://idp.example.org">
+ <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
MIIDtTCCAp2gAwIBAgIJAPmsD+VGldyPMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDExMTMzOTE4WhcNMjQwNDA4MTMzOTE4WjBF
@@ -53,15 +54,55 @@ BkgVPOuVuEe803BRlKd4BVIsuxAUAy3oqdJYqf9ptPEx8Ef+ALbcDhRbWINhMgO7
8oFt0blzXtQ2vcOVyNyG326uZBZv2Cf6FXFsYQX1L/tLeTBJegefgGkg2dqCTKIU
1Qy/Kd2P3/S01kQxjDeG7UfXc9qtelJ68kvzK2d3WOJ2qmsdMxjMNfTItP7FO54M
i8V7gp9HK+EimdSbgu7xktKlrqA2Rsn+dBoPSgOUs/LOGtCS9/biF0w=
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </md:KeyDescriptor>
- <md:SingleSignOnService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
- Location="https://idp.example.org/idp/profile/SAML2/SSO/Redirect" />
- </md:IDPSSODescriptor>
- </md:EntityDescriptor>
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:SingleSignOnService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+ Location="https://idp.example.org/idp/profile/SAML2/Redirect/SSO" />
+ <md:SingleSignOnService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://idp.example.org/idp/profile/SAML2/POST/SSO" />
+ </md:IDPSSODescriptor>
+ </md:EntityDescriptor>
+
+ <md:EntityDescriptor entityID="https://noendpoint.example.org">
+ <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <md:KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+MIIDtTCCAp2gAwIBAgIJAPmsD+VGldyPMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDExMTMzOTE4WhcNMjQwNDA4MTMzOTE4WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxg0TyQAP/tIvOH89EtaXuRRn8SYzTj7W1TbNY4VvBmobjkRmSkki4hH9
+x4sQpi635wn6WtXTN/FNNmkTK3N/LspmBWxfZS+n+cc7I82E5yvCAPX67QsZgqgg
+lp2W5dvK/FsMMCS6X6SVqzBLMP88NenXKxY+HMxMs0sT0UKYh1cAEqadrHRBO65a
+DBcm5a0sBVYt9K6pgaOHrp/zSIbhnR5tFFLjBbtFktDpHL3AdGBH3OYidNGKBO3t
+J3Ms7LeKXsM0+0Y4P+9fHZINL2X3E2N6GVnKs5PZTg9sP0FtIpAbYm/+zCx7Yj1E
+T/Er8mDd6tNVGSQsn9s5xUBwGqn14wIDAQABo4GnMIGkMB0GA1UdDgQWBBSiQhSu
+p9BYjD2ZuMkEiQK7w/Zq0TB1BgNVHSMEbjBsgBSiQhSup9BYjD2ZuMkEiQK7w/Zq
+0aFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
+BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAPmsD+VGldyPMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHZmIo9GBTSsD5DJfKkCVUvBafwR089H
+BkgVPOuVuEe803BRlKd4BVIsuxAUAy3oqdJYqf9ptPEx8Ef+ALbcDhRbWINhMgO7
+0/S4x3pS9gOn7/Y9yZplOe4Jd2q3R8QBef+hKLcD/Uv0Sqy2nilM8BnMga5tqsL+
+8oFt0blzXtQ2vcOVyNyG326uZBZv2Cf6FXFsYQX1L/tLeTBJegefgGkg2dqCTKIU
+1Qy/Kd2P3/S01kQxjDeG7UfXc9qtelJ68kvzK2d3WOJ2qmsdMxjMNfTItP7FO54M
+i8V7gp9HK+EimdSbgu7xktKlrqA2Rsn+dBoPSgOUs/LOGtCS9/biF0w=
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </md:KeyDescriptor>
+ <md:SingleSignOnService
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
+ Location="https://idp.example.org/idp/profile/SAML2/Artifact/SSO" />
+ </md:IDPSSODescriptor>
+ </md:EntityDescriptor>
+ </md:EntitiesDescriptor>
</MetadataProvider>
</MetadataProvider>
diff --git a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/test-agents.xml b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/test-agents.xml
index 15a3693..c12021f 100644
--- a/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/test-agents.xml
+++ b/sp-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/test-agents.xml
@@ -27,6 +27,10 @@
p:issuer="https://testsp.example.org"
p:authenticatingAuthority="https://idp.example.org"
p:defaultConfiguration-ref="shibboleth.UnverifiedRelyingParty" />
+
+ <bean p:id="no-endpoint" parent="shibboleth.Application"
+ p:issuer="https://testsp.example.org"
+ p:authenticatingAuthority="https://noendpoint.example.org" />
<bean p:id="no-initiators" parent="shibboleth.Application"
p:issuer="https://testsp.example.org"
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java
index 5c5555f..d053eec 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java
@@ -285,6 +285,8 @@ public class AddAuthnRequest extends AbstractApplicationAction {
final MessageContext omc = profileRequestContext.getOutboundMessageContext();
assert omc != null;
omc.setMessage(object);
+
+ log.info("{} Generated AuthnRequest with ID {} from {}", getLogPrefix(), object.getID(), issuerId);
}
/**
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java
index 93037c1..710b3ad 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/AbstractAgentRequestAction.java
@@ -30,6 +30,7 @@ import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.sp.Agent;
+import net.shibboleth.sp.Application;
import net.shibboleth.sp.context.AgentRequestContext;
/**
@@ -46,6 +47,9 @@ public abstract class AbstractAgentRequestAction extends AbstractProfileAction {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AbstractAgentRequestAction.class);
+ /** Local copy of extended log prefix. */
+ @Nullable private String logPrefix;
+
/** Lookup strategy for {@link AgentRequestContext}. */
@Nonnull private Function<ProfileRequestContext,AgentRequestContext> agentRequestContextLookupStrategy;
@@ -107,19 +111,31 @@ public abstract class AbstractAgentRequestAction extends AbstractProfileAction {
}
/** {@inheritDoc} */
- @SuppressWarnings("null")
@Override
@Nonnull protected String getLogPrefix() {
- final StringBuilder s = new StringBuilder(super.getLogPrefix());
+
+ if (logPrefix != null) {
+ return logPrefix;
+ }
+
+ final StringBuilder s = new StringBuilder();
final AgentRequestContext ctx = getAgentRequestContext();
if (ctx != null) {
final Agent agent = ctx.getAgent();
if (agent != null) {
- s.append(" Agent ").append(agent.getId()).append(":");
+ s.append("Agent ").append(agent.getId()).append(":");
+ }
+ final Application app = ctx.getApplication();
+ if (app != null) {
+ s.append(" Application ").append(app.getId()).append(": ");
}
}
- return s.toString();
+ s.append(super.getLogPrefix());
+ logPrefix = s.toString();
+
+ assert logPrefix != null;
+ return logPrefix;
}
}
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/EncodeMessage.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/EncodeMessage.java
index ad60f7a..7b84503 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/EncodeMessage.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/EncodeMessage.java
@@ -57,7 +57,8 @@ public class EncodeMessage extends org.opensaml.profile.action.impl.EncodeMessag
if (createOutputObjects) {
final DDF output = new DDF(null);
agentRequestContext.setOutput(output);
- agentRequestContext.setRemotedHttpServletResponse(new RemotedHttpServletResponse(output));
+ agentRequestContext.setRemotedHttpServletResponse(
+ new RemotedHttpServletResponse(output.structure().addmember("http")));
}
try {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list