[java-plugin-shibd-oidc] branch main updated: Improve tests
Codeberg
noreply at shibboleth.net
Mon Apr 13 12:57:11 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-plugin-shibd-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-oidc/commit/f30ea30a4ebf93995239296dcfd1f3e94f14eaef
The following commit(s) were added to refs/heads/main by this push:
new f30ea30 Improve tests
f30ea30 is described below
commit f30ea30a4ebf93995239296dcfd1f3e94f14eaef
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Mon Apr 13 13:56:58 2026 +0100
Improve tests
---
.../sp/oidc/flows/OIDCTokenConsumerFlowTest.java | 113 +++++++--------------
.../shibboleth/sp/oidc/flows/TestConstants.java | 12 ++-
2 files changed, 43 insertions(+), 82 deletions(-)
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
index 8812cfb..f0414d6 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCTokenConsumerFlowTest.java
@@ -17,7 +17,6 @@ package net.shibboleth.sp.oidc.flows;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -29,6 +28,7 @@ import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -41,13 +41,8 @@ import org.apache.hc.core5.http.io.HttpClientResponseHandler;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.mockito.Mockito;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.io.UnmarshallingException;
-import org.opensaml.core.xml.util.XMLObjectSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.saml.saml2.core.NameID;
-import org.opensaml.saml.saml2.core.NameIDType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
@@ -88,11 +83,8 @@ import net.minidev.json.JSONObject;
import net.shibboleth.idp.spring.IdPPropertiesApplicationContextInitializer;
import net.shibboleth.idp.test.PreferFileSystemApplicationContextInitializer;
import net.shibboleth.oidc.security.credential.JWKCredential;
-import net.shibboleth.shared.codec.Base64Support;
-import net.shibboleth.shared.codec.DecodingException;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.xml.XMLParserException;
import net.shibboleth.sp.context.AgentRequestContext;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.flows.AbstractSPFlowTest;
@@ -737,7 +729,9 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
final FlowExecutionResult result = flowExecutor.launchExecution(TestConstants.FLOW_ID, null, externalContext);
assertFlowExecutionResult(result, TestConstants.FLOW_ID);
assertFlowExecutionOutcome(result.getOutcome());
- assertOutputMessageEvent(result, EventIds.MESSAGE_PROC_ERROR);
+ final DDF output = assertOutputMessageEvent(result, EventIds.MESSAGE_PROC_ERROR);
+ System.out.println("DDF: "+output.toString());
+ validateCookiesAreUnset(output);
}
@@ -920,7 +914,34 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
.thenReturn(classicHttpResponse);
}
-
+ /**
+ * Check that the output message contains an instruction to unset cookies using Max-Age=0, and specifically the
+ * correlation cookie.
+ *
+ * @param output the DDF output
+ */
+ private void validateCookiesAreUnset(@Nullable final DDF output) {
+ if (output == null) {
+ fail("DDF output can not be null");
+ }
+ // Check cookies are unset
+ final DDF headers = output.getmember("http.headers");
+ // Check that any Set-Cookie is an unset, we do not set new cookies in the consumer flow
+ final AtomicBoolean correlationCookieUnset = new AtomicBoolean(false);
+ if (headers.islist()) {
+ headers.forEach(header -> {
+ if (header.isstring() && "Set-Cookie".equals(header.name())){
+ Assert.assertTrue(header.string().contains("Max-Age=0"),"Cookies must be unset");
+ }
+ // Specific check for the correlation cookie unset, which is required
+ if (header.string().contains(TestConstants.CORRELATION_COOKIE_PREFIX)) {
+ Assert.assertTrue(header.string().contains("Max-Age=0"),"Correlation cookies must be unset");
+ correlationCookieUnset.set(true);
+ }
+ });
+ }
+ Assert.assertTrue(correlationCookieUnset.get(),"Correlation cookies must be unset");
+ }
/**
* Decode an encoded response and run assertion checks against it.
@@ -968,6 +989,8 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
}
}
Assert.assertTrue(mutableIds.isEmpty());
+
+ validateCookiesAreUnset(output);
//TODO ADD BACK
// try {
@@ -997,74 +1020,6 @@ public class OIDCTokenConsumerFlowTest extends AbstractSPFlowTest {
}
- /**
- * Decode an encoded response and run sanity checks against it.
- *
- * @param result flow execution result
- * @param attributeIds set of attribute IDs to check for
- * @param resource resource URL used in final redirect
- * @param sessionIndex SessionIndex from assertion
- *
- * @return the output object
- *
- * TODO from the SAML variant.
- */
- @Nonnull private DDF validateOutputMessage(@Nonnull final FlowExecutionResult result,
- @Nullable final Set<String> attributeIds, @Nullable final String resource, @Nullable final String sessionIndex) {
- final ProfileRequestContext prc = retrieveProfileRequestContext(result);
- assert prc != null;
- final AgentRequestContext arc = prc.ensureSubcontext(AgentRequestContext.class);
- final DDF output = arc.getOutput();
-
- assert output != null;
- Assert.assertTrue(output.isstruct());
- final DDF http = output.getmember(RemotedHttpServletRequest.STRUCTURE_NAME);
- Assert.assertTrue(http.isstruct());
-
- final byte[] redirect = http.getmember(RemotedHttpServletResponse.REDIRECT).unsafe_string();
- Assert.assertEquals(resource != null ? resource.getBytes(StandardCharsets.UTF_8) : null, redirect);
-
- Assert.assertTrue(output.getmember(ConsumerConstants.VALIDATION_ERRORS).isnull());
-
- final Set<String> mutableIds = new HashSet<>(attributeIds);
- for (final DDF attr : output.getmember(ConsumerConstants.SESSION_ATTRIBUTES).asList()) {
- Assert.assertTrue(mutableIds.contains(attr.name()));
- mutableIds.remove(attr.name());
- if ("mail".equals(attr.name())) {
- Assert.assertEquals(attr.asList().stream().map(DDF::string).toList(),
- CollectionSupport.singletonList("jdoe at example.org"));
- } else if ("displayName".equals(attr.name())) {
- Assert.assertEquals(attr.asList().stream().map(DDF::string).toList(),
- CollectionSupport.singletonList("John Doe"));
- } else if ("eduPersonScopedAffiliation".equals(attr.name())) {
- Assert.assertEquals(attr.asList().stream().map(ddf -> {return ddf.getmember("value").string();}).toList(),
- CollectionSupport.listOf("member"));
- Assert.assertEquals(attr.asList().stream().map(ddf -> {return ddf.getmember("scope").string();}).toList(),
- CollectionSupport.listOf("example.org"));
- }
- }
- Assert.assertTrue(mutableIds.isEmpty());
-
- try {
- final String s = output.getmember(ConsumerConstants.SESSION_OPAQUE).string();
- assert s != null;
- final byte[] opaque = Base64Support.decodeURLSafe(s);
- try (final ByteArrayInputStream in = new ByteArrayInputStream(opaque)) {
- final XMLObject obj = XMLObjectSupport.unmarshallFromInputStream(parserPool, in);
- if (obj instanceof final NameID nameID) {
- Assert.assertEquals(nameID.getValue(), "jdoe at example.org");
- Assert.assertEquals(nameID.getFormat(), NameIDType.EMAIL);
- Assert.assertEquals(nameID.getSPProvidedID(), sessionIndex);
- } else {
- Assert.fail("Session data was not a NameID");
- }
- }
- } catch (final DecodingException|IOException|UnmarshallingException|XMLParserException e) {
- Assert.fail(e.getMessage());
- }
-
- return output;
- }
/**
* Builds a dummy OIDC authorization code response.
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java
index 5408668..9883156 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/TestConstants.java
@@ -94,6 +94,12 @@ public final class TestConstants {
/** Target URL encoded in cookie. */
public static final String TARGET_URL = "https://sp.example.org/secure";
+ /** The defaulted prefix of the correlation cookie.*/
+ public static final String CORRELATION_COOKIE_PREFIX = "__Host-shibsp_req_";
+
+ /** The defaulted prefix for state tokens.*/
+ public static final String STATE_TOKEN_PREFIX = "__Host-shibsp_state__";
+
/**
* Build cookie header bytes for the given parameters. These take the form of:
* <pre>
@@ -122,11 +128,11 @@ public final class TestConstants {
// Compose the header with semicolons and spacing as in the example
final StringBuilder sb = new StringBuilder();
- sb.append("__Host-shibsp_req_").append(stateToken).append('=')
+ sb.append(CORRELATION_COOKIE_PREFIX).append(stateToken).append('=')
.append(buildCorrelationCookieString(authnStateToken, rfp)).append(";\n");
- sb.append("__Host-shibsp_state__").append(appID).append('_').append(stateToken)
+ sb.append(STATE_TOKEN_PREFIX).append(appID).append('_').append(stateToken)
.append('=').append(targetUrlB64).append("; \n");
- sb.append("__Host-shibsp_state__").append(appID).append('_').append(authnStateToken).append('=').append(authnJsonEnc).append(";\n");
+ sb.append(STATE_TOKEN_PREFIX).append(appID).append('_').append(authnStateToken).append('=').append(authnJsonEnc).append(";\n");
System.out.println(sb.toString());
return sb.toString().getBytes("UTF-8");
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list