[java-plugin-shibd-oidc] branch main updated: Add flow tests for requested claims from the hub config

Phil Smart philip.smart at jisc.ac.uk
Wed Oct 15 13:09:01 UTC 2025


This is an automated email from the git hooks/post-receive script.

philsmart pushed a commit to branch main
in repository java-plugin-shibd-oidc.

View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd-oidc.git;a=commit;h=8ff2e95f622f9eb1d9288fdbcacfffbec74d08c0

The following commit(s) were added to refs/heads/main by this push:
     new 8ff2e95  Add flow tests for requested claims from the hub config
8ff2e95 is described below

commit 8ff2e95f622f9eb1d9288fdbcacfffbec74d08c0
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Oct 15 14:08:58 2025 +0100

    Add flow tests for requested claims from the hub config
---
 .../sp/oidc/flows/OIDCAuthenticationFlowTest.java  | 74 ++++++++++++++++++++++
 .../functions/RequestedClaimsExampleFunction.java  | 32 ++++++++++
 .../resources/metadata/openid-configuration.json   |  1 +
 .../idp/module/conf/sp/oidc-test-agents.xml        | 13 +++-
 4 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java
index 2974835..f8621b9 100644
--- a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/flows/OIDCAuthenticationFlowTest.java
@@ -31,6 +31,7 @@ import org.opensaml.saml.common.binding.SAMLBindingSupport;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.util.ObjectUtils;
+import org.springframework.webflow.engine.impl.FlowExecutionImpl;
 import org.springframework.webflow.executor.FlowExecutionResult;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -41,6 +42,7 @@ import com.nimbusds.jwt.SignedJWT;
 import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
 
+import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.sp.context.AgentRequestContext;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.flows.AbstractSPFlowTest;
@@ -203,6 +205,30 @@ public class OIDCAuthenticationFlowTest extends AbstractSPFlowTest {
         assertValueForParameterFromRequestObject(req, "acr_values", "loa1 loa2");
     }
     
+    /**
+     * Basic flow test with requested claims from the RP config. The RP config is set onto
+     * the application test-oidc-application-with-requested-attrs.
+     * 
+     * @throws Exception on error
+     */
+    @Test
+    public void testRequestedClaimsFromHub() throws Exception {
+        setDefaultAuth();
+        
+        final DDF input = new DDF(null).structure();
+        input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();        
+        input.addmember(InitiatorConstants.RESPONSE_URL).string(RESPONSE_URL);
+        input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);        
+        setApplicationRequest("test-oidc-application-with-requested-attrs", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        final AuthenticationRequest req = validateOutputMessage(result);
+        assertValueForParameterExistInRequestObject(req, "claims");
+    }
+    
     /**
      * Basic flow test with two resource indicators.
      * 
@@ -305,6 +331,27 @@ public class OIDCAuthenticationFlowTest extends AbstractSPFlowTest {
         assertValueForParameterFromRequestObject(req, "display", "page");
     }
     
+    /**
+     * Get the profile request context from the conversation scope.
+     * 
+     * @param flowExec the flow execution
+     * @return the profile request context
+     */
+    protected ProfileRequestContext getProfileRequestContextFromConversation(final FlowExecutionImpl flowExec) {
+        return (ProfileRequestContext) flowExec.getConversationScope().get(ProfileRequestContext.BINDING_KEY);
+    }
+    
+    /**
+     * Get the relying party context from the conversation scope.
+     * 
+     * @param flowExec the flow execution
+     * @return the relying party context
+     */
+    protected RelyingPartyContext getRelyingPartyContextFromConversation(final FlowExecutionImpl flowExec) {
+        final var prc = (ProfileRequestContext) flowExec.getConversationScope().get(ProfileRequestContext.BINDING_KEY);
+        return prc.ensureSubcontext(RelyingPartyContext.class);
+    }
+    
     /**
      * Decode an encoded response and run sanity checks against it.
      * 
@@ -381,6 +428,7 @@ public class OIDCAuthenticationFlowTest extends AbstractSPFlowTest {
      * 
      * @param request the request to locate the parameter from
      * @param claim the claim to find
+     * @param expectedClaimValue the expected value
      * 
      * @throws java.text.ParseException 
      */
@@ -401,6 +449,32 @@ public class OIDCAuthenticationFlowTest extends AbstractSPFlowTest {
         assertTrue(ObjectUtils.nullSafeEquals(claimValue, expectedClaimValue));
     }
     
+    /**
+     * Assert that the String value for the given parameter from the {@link AuthenticationRequest} is
+     * not null inside a claim in the Request Object.
+     * 
+     * @param request the request to locate the parameter from
+     * @param claim the claim to find
+     * 
+     * @throws java.text.ParseException 
+     */
+    private void assertValueForParameterExistInRequestObject(final AuthenticationRequest request, 
+            @Nonnull final String claim) throws java.text.ParseException {
+        
+        JWTClaimsSet requestObjectClaims = null;
+        if (request.getRequestObject() instanceof final SignedJWT signed) {
+            requestObjectClaims = signed.getJWTClaimsSet();
+        } else if (request.getRequestObject() instanceof final PlainJWT jwt){
+            requestObjectClaims = jwt.getJWTClaimsSet();
+        }
+        
+        Object claimValue = null;
+        if (requestObjectClaims != null) {
+            claimValue = requestObjectClaims.getClaim(claim);
+        }
+        assertNotNull(claimValue);
+    }
+    
     /**
      * Decodes an OAuth authorization message encoded via HTTP-Redirect binding.
      * 
diff --git a/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/functions/RequestedClaimsExampleFunction.java b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/functions/RequestedClaimsExampleFunction.java
new file mode 100644
index 0000000..5456662
--- /dev/null
+++ b/sp-oidc-conf-impl/src/test/java/net/shibboleth/sp/oidc/functions/RequestedClaimsExampleFunction.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.sp.oidc.functions;
+
+import java.util.Map;
+import java.util.function.Function;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+/**
+ * A function that returns an example requested claims map.
+ */
+public class RequestedClaimsExampleFunction implements Function<ProfileRequestContext, Map<String, Object>>{
+
+    /** {@inheritDoc} */
+    @Override
+    public Map<String, Object> apply(final ProfileRequestContext input) {
+        return Map.of("id_token", Map.of("email", Map.of("essential", true)));
+    }
+}
diff --git a/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json b/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json
index d04036c..9433cbb 100644
--- a/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json
+++ b/sp-oidc-conf-impl/src/test/resources/metadata/openid-configuration.json
@@ -30,6 +30,7 @@
 "email",
 "profile"
 ],
+"claims_parameter_supported" : true,
 "token_endpoint_auth_methods_supported": [
 "client_secret_post",
 "client_secret_basic"
diff --git a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
index cbbd2dd..3bdc8d5 100644
--- a/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
+++ b/sp-oidc-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/oidc-test-agents.xml
@@ -25,6 +25,9 @@
                 <bean p:id="test-oidc-application" parent="shibboleth.sp.Application"
                     p:profileConfigurations-ref="test.ProfileConfigurations" 
                     p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"/>
+                <bean p:id="test-oidc-application-with-requested-attrs" parent="shibboleth.sp.Application"
+                    p:profileConfigurations-ref="test.ProfileConfigurations" 
+                    p:metadataResolver-ref="shibboleth.ProviderMetadataResolverService"/>
             </set>
         </property>
     </bean>
@@ -36,10 +39,18 @@
         <bean parent="OIDC.SSO" p:securityConfiguration-ref="testSecConfig"/>
     </util:list>
     
+    <util:list id="test.ProfileConfigurations">
+        <bean parent="OIDC.SSO" p:securityConfiguration-ref="testSecConfig">
+            <property name="requestedClaimsLookupStrategy">
+                <bean id="basicRequestedClaims" class="net.shibboleth.sp.oidc.functions.RequestedClaimsExampleFunction"/>
+            </property>        
+        </bean>
+    </util:list>
+    
     <!-- 
         Overrides the default security configuration to provide an encryption credential resolver
         that loads JWKs from a local file instead of retrieving them from the issuer’s JWKS URI.
-        This simplifies testing by avoiding reliance on an external JWKS endpoint. We also constraint
+        This simplifies testing by avoiding reliance on an external JWKS endpoint. We also constrain
         the algorithms used, to simplify baseline tests.
      -->
     <bean id="testSecConfig" parent="shibboleth.oidc.DefaultSecurityConfiguration">

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list