[java-idp-plugin-oidc-op-oidfed] branch main updated: Add activation condiiton to the federation request object validators.

Henri Mikkonen henri.mikkonen at iki.fi
Tue Sep 16 07:24:30 UTC 2025


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

hjmikkon pushed a commit to branch main
in repository java-idp-plugin-oidc-op-oidfed.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-oidc-op-oidfed.git;a=commit;h=f1b7fdb89cc75e6289e4f098564b4e55f0ef2384

The following commit(s) were added to refs/heads/main by this push:
     new f1b7fdb  Add activation condiiton to the federation request object validators.
f1b7fdb is described below

commit f1b7fdb89cc75e6289e4f098564b4e55f0ef2384
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Tue Sep 16 10:24:07 2025 +0300

    Add activation condiiton to the federation request object validators.
    
    - They need to activate solely if the automatic registration sequence is being used.
    - Improved tests to make sure that standard OIDC sequences still work normally.
---
 .../META-INF/net.shibboleth.idp/postconfig.xml     | 11 +++-
 .../AuthorizeFlowAutomaticRegistrationTest.java    | 75 ++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 250fb93..e37696b 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -464,9 +464,14 @@
         </constructor-arg>
     </bean>
 
+    <bean id="shibboleth.oidfed.RequestObjectValidationCondition"
+        parent="shibboleth.BiConditions.Expression"
+        c:expression="#input1.ensureInboundMessageContext().containsSubcontext(T(net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.RelyingPartyTrustChainContext)) and #input1.ensureInboundMessageContext().ensureSubcontext(T(net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.RelyingPartyTrustChainContext)).getSelectedTrustChain() != null"/>
+
     <util:list id="FederationClaimsValidators" value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.AudienceClaimsValidator"
-            p:extraAudienceValidation="true">
+            p:extraAudienceValidation="true"
+            p:activationCondition-ref="shibboleth.oidfed.RequestObjectValidationCondition">
             <property name="audienceLookupStrategy">
                 <bean parent="shibboleth.BiFunctions.Expression"
                     c:expression="#custom.apply(#input1)"
@@ -475,12 +480,16 @@
         </bean>
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.JWTIdentifierClaimsValidator"
             p:clockSkew="%{idp.policy.clockSkew:PT1M}"
+            p:activationCondition-ref="shibboleth.oidfed.RequestObjectValidationCondition"
             p:replayCache-ref="shibboleth.ReplayCache" />
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+            p:activationCondition-ref="shibboleth.oidfed.RequestObjectValidationCondition"
             p:requiredClaims="exp" />
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ProhibitedClaimsValidator"
+            p:activationCondition-ref="shibboleth.oidfed.RequestObjectValidationCondition"
             p:prohibitedClaims="sub" />
         <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExactMatchClaimsValidator"
+            p:activationCondition-ref="shibboleth.oidfed.RequestObjectValidationCondition"
             p:claimName="client_id">
             <property name="valueToMatchLookupStrategy">
                 <bean parent="shibboleth.BiFunctions.Expression"
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
index 7f6ddc7..9c4d31c 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
@@ -22,20 +22,28 @@ import java.net.URLEncoder;
 import java.text.ParseException;
 import java.time.Duration;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import org.opensaml.storage.StorageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.webflow.executor.FlowExecutionResult;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.jose.JOSEException;
 import com.nimbusds.jose.jwk.JWKSet;
 import com.nimbusds.jwt.JWT;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
+import com.nimbusds.oauth2.sdk.Scope;
 import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
 import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
@@ -43,12 +51,17 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
 import net.shibboleth.idp.plugin.oidc.op.profile.flow.AuthorizeFlowTest;
 import net.shibboleth.idp.plugin.oidc.op.profile.logic.DefaultPushedAuthorizationRequestUriSerializationFunction;
 import net.shibboleth.idp.plugin.oidc.op.token.support.AuthorizeCodeClaimsSet;
+import net.shibboleth.idp.session.SessionException;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.security.DataSealerException;
 
 public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFlowTest {
 
+    @Autowired
+    @Qualifier("shibboleth.StorageService")
+    StorageService storageService;
+
     public AuthorizeFlowAutomaticRegistrationTest() {
         super(AuthorizeFlowTest.FLOW_ID);
     }
@@ -395,6 +408,68 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
         Assert.assertEquals(unwrapTrustChainFromAuthorizeCode(successResponse), List.of(clientId, anchorId));
     }
 
+    @Test
+    public void testWithValinnaOIDC() throws IOException, ParseException,
+            SessionException, JOSEException {
+        assertVanillaClient("mockClientId", null, null);
+    }
+
+    @Test
+    public void testWithValinnaOIDCPlainRequestObject() throws IOException, ParseException,
+            SessionException, JOSEException {
+        final String clientId = "mockClientId";
+
+        final JWTClaimsSet ro = new JWTClaimsSet.Builder()
+                .audience(issuer)
+                .issuer(clientId)
+                .claim("redirect_uri", redirectUri)
+                .build();
+        assertVanillaClient(clientId, null, new PlainJWT(ro));
+    }
+
+    @Test
+    public void testWithValinnaOIDCSignedRequestObject() throws IOException, ParseException,
+            SessionException, JOSEException {
+        final String clientId = "mockClientId";
+        final String clientSecret = "mockClientSecretmockClientSecretmockClientSecretmockClientSecretmockClientSecret";
+
+        final JWTClaimsSet ro = new JWTClaimsSet.Builder()
+                .audience(issuer)
+                .issuer(clientId)
+                .claim("redirect_uri", redirectUri)
+                .build();
+        assertVanillaClient(clientId, clientSecret, createSecretJWT(ro, clientSecret));
+    }
+
+    protected void assertVanillaClient(final String clientId, final String clientSecret, final JWT requestObject)
+            throws IOException {
+        request.setMethod("GET");
+        final List<Pair<String,String>> requestParameters = new ArrayList<>(List.of(new Pair<>("client_id", clientId),
+                new Pair<>("response_type", "code"),
+                new Pair<>("redirect_uri", redirectUri),
+                new Pair<>("scope", "openid profile")));
+        if (requestObject != null) {
+            requestParameters.add(new Pair<>("request", requestObject.serialize()));
+        }
+        setQueryParameters(request, requestParameters);
+        storeMetadata(storageService, clientId, clientSecret, Scope.parse("openid profile"), redirectUri);
+
+        setBasicAuth("jdoe", "changeit");
+        initializeThreadLocals();
+
+        final FlowExecutionResult result =
+                flowExecutor.launchExecution(AuthorizeFlowTest.FLOW_ID, null, externalContext);
+        final AuthenticationResponse responseMessage = parseSuccessResponse(result, AuthenticationResponse.class);
+        final AuthenticationSuccessResponse successResponse = responseMessage.toSuccessResponse();
+        Assert.assertEquals(successResponse.getRedirectionURI().toString(), redirectUri);
+        Assert.assertNull(successResponse.getIDToken());
+        Assert.assertNull(successResponse.getAccessToken());
+        Assert.assertNotNull(successResponse.getAuthorizationCode());
+        Assert.assertNull(successResponse.getIssuer());
+
+        removeMetadata(storageService, clientId);
+    }
+
     protected URI createParGeneratedRequestUri(final Map<String, Object> parameters,
             final List<String> trustChain) {
         final DefaultPushedAuthorizationRequestUriSerializationFunction parGenerator =

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


More information about the commits mailing list