[java-idp-plugin-oidc-op-oidfed] 02/02: Improved error response contents

Henri Mikkonen henri.mikkonen at iki.fi
Wed Oct 8 11:49:41 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=4432a0d7051d95b17d420abdbdcd0c191c7a9b3c

commit 4432a0d7051d95b17d420abdbdcd0c191c7a9b3c
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Oct 8 14:48:54 2025 +0300

    Improved error response contents
    
    - New event ID to signal if no trust chains could be resolved "NoTrustChainsResolved"
      - Event mapped to PAR and explicit registration responses
    - Explicit registration exploits new map 'shibboleth.oidfed.register.DefaultMappedErrors'
      - It extends the OIDC dynamic client registration's mapped errors
      - May be overridden by 'shibboleth.oidfed.register.MappedErrors'
---
 .../oidfed/profile/impl/OidFederationEventIds.java |  5 +++++
 .../op/oidfed/profile/impl/ResolveTrustChains.java |  4 +++-
 .../op/oidfed/profile/impl/SelectTrustChain.java   |  1 +
 .../META-INF/net.shibboleth.idp/postconfig.xml     | 24 ++++++++++++++++++++++
 .../oidfed/metadata-lookup-ext-oidfed-beans.xml    |  7 +------
 .../oidfed/metadata-lookup-ext-oidfed-flow.xml     |  2 ++
 .../idp/flows/oidfed/register/register-beans.xml   | 13 ++++++------
 .../profile/flow/oidfed/RegistrationFlowTest.java  | 10 ++++-----
 8 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
index 2558d9f..ec5bbbe 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
@@ -40,6 +40,11 @@ public class OidFederationEventIds {
     @Nonnull @NotEmpty public static final String CACHED_ENTITY_CONFIGURATION_RESPONSE =
             "CachedEntityConfigurationResponseFound";
 
+    /**
+     * ID of event returned if no trust chains were resolved for the client.
+     */
+    @Nonnull @NotEmpty public static final String NO_TRUST_CHAINS_RESOLVED = "NoTrustChainsResolved";
+
     /**
      * ID of event returned if the given trust anchor is invalid.
      */
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
index dd942fa..3607b51 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
@@ -221,10 +221,12 @@ public class ResolveTrustChains extends AbstractTrustChainResolutionAction {
             cacheResult = trustChainCache.get(criteriaSet);
         } catch (final MetadataCacheException e) {
             log.warn("{} Could fetch trust chains for {}", getLogPrefix(), clientId);
+            ActionSupport.buildEvent(profileRequestContext, OidFederationEventIds.NO_TRUST_CHAINS_RESOLVED);
             return;
         }
         if (cacheResult.isEmpty()) {
             log.debug("{} No trust chains resolved for {}", getLogPrefix(), clientId);
+            ActionSupport.buildEvent(profileRequestContext, OidFederationEventIds.NO_TRUST_CHAINS_RESOLVED);
             return;
         }
         final List<String> preSelectedChain =
@@ -249,7 +251,7 @@ public class ResolveTrustChains extends AbstractTrustChainResolutionAction {
 
         if (policyCompliantChains.isEmpty()) {
             if (errorEventId == null) {
-                ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+                ActionSupport.buildEvent(profileRequestContext, OidFederationEventIds.NO_TRUST_CHAINS_RESOLVED);
             } else {
                 ActionSupport.buildEvent(profileRequestContext, errorEventId);
             }
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
index 085ffdb..77e4e34 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
@@ -139,6 +139,7 @@ public class SelectTrustChain extends AbstractProfileAction {
         trustChainContext = trustChainContextLookupStrategy.apply(profileRequestContext);
         if (trustChainContext == null || trustChainContext.getPolicyCompliantTrustChains() == null) {
             log.debug("{} Unable to locate policy-compliant trust chains, nothing to do", getLogPrefix());
+            ActionSupport.buildEvent(profileRequestContext, OidFederationEventIds.NO_TRUST_CHAINS_RESOLVED);
             return false;
         }
         return true;
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 a94a38f..cb15816 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
@@ -386,6 +386,21 @@
         </property>
     </bean>
 
+    <bean id="shibboleth.oidfed.register.DefaultMappedErrors"
+            parent="shibboleth.oidc.register.DefaultMappedErrors"
+            class="org.springframework.beans.factory.config.MapFactoryBean">
+        <property name="sourceMap">
+            <map value-type="com.nimbusds.oauth2.sdk.ErrorObject">
+                <entry>
+                    <key>
+                        <util:constant static-field="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.OidFederationEventIds.NO_TRUST_CHAINS_RESOLVED"/>
+                    </key>
+                    <bean class="com.nimbusds.oauth2.sdk.ErrorObject" c:_0="invalid_client" c:_1="No acceptable trust chains could be resolved for the client" c:_2="401" />
+                </entry>
+            </map>
+        </property>
+    </bean>
+
     <bean id="DefaultTrustMarkClaimsValidationLookupStrategy" parent="shibboleth.Functions.Constant">
         <constructor-arg name="target">
             <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator">
@@ -564,6 +579,15 @@
         </property>
     </bean>
 
+    <bean parent="shibboleth.oidc.PushedAuthorizationErrorMapping">
+        <property name="eventId">
+            <util:constant static-field="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.OidFederationEventIds.NO_TRUST_CHAINS_RESOLVED"/>
+        </property>
+        <property name="errorObject">
+            <bean class="com.nimbusds.oauth2.sdk.ErrorObject" c:_0="invalid_client" c:_1="No acceptable trust chains could be resolved for the client" c:_2="401" />
+        </property>
+    </bean>
+
     <alias alias="UseResolverApiCondition" name="%{idp.oidfed.trustchain.resolver.useResolverApiCondition:shibboleth.Conditions.FALSE}" />
     <alias alias="FallbackToLocalResolutionCondition" name="%{idp.oidfed.trustchain.resolver.fallbackToLocalCondition:shibboleth.Conditions.TRUE}" />
 
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
index 4a4cacc..3c502ef 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
@@ -101,12 +101,7 @@
         p:profileId="#{T(net.shibboleth.idp.plugin.oidc.op.oidfed.config.OIDFederationAutomaticRegistrationProfileConfiguration).PROFILE_ID}" />
 
     <bean id="SelectTrustChain" class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.SelectTrustChain"
-        scope="prototype">
-        <property name="activationCondition">
-            <bean parent="shibboleth.Conditions.Expression"
-                c:expression="#input.ensureInboundMessageContext().containsSubcontext(T(net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.RelyingPartyTrustChainContext))" />
-        </property>
-    </bean>
+        scope="prototype"/>
 
     <bean id="ResolveTrustMarks" class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.ResolveTrustMarks"
         scope="prototype"
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml
index 51d6133..bbe8d1a 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml
@@ -59,11 +59,13 @@
     <end-state id="proceed"/>
     <end-state id="InvalidMetadataPolicy"/>
     <end-state id="InvalidMetadataAgainstPolicy"/>
+    <end-state id="NoTrustChainsResolved" />
     <end-state id="HandleError"/>
 
     <global-transitions>
         <transition on="InvalidMetadataPolicy" to="InvalidMetadataPolicy" />
         <transition on="InvalidMetadataAgainstPolicy" to="InvalidMetadataAgainstPolicy" />
+        <transition on="NoTrustChainsResolved" to="NoTrustChainsResolved" />
         <transition on="HandleError" to="HandleError" />
     </global-transitions>
 
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
index 8b6529c..bd090cc 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
@@ -179,12 +179,7 @@
 
     <bean id="SelectTrustChain" class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.SelectTrustChain"
         scope="prototype"
-        p:relyingPartyContextCreationStrategy-ref="ExplicitRegistrationRelyingPartyCreationStrategy">
-        <property name="activationCondition">
-            <bean parent="shibboleth.Conditions.Expression"
-                c:expression="#input.ensureInboundMessageContext().containsSubcontext(T(net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.RelyingPartyTrustChainContext))" />
-        </property>
-    </bean>
+        p:relyingPartyContextCreationStrategy-ref="ExplicitRegistrationRelyingPartyCreationStrategy"/>
 
     <bean id="ResolveTrustMarks" class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.ResolveTrustMarks"
         scope="prototype"
@@ -201,6 +196,10 @@
             <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultTrustChainTrustedTrustMarkOwnersLookupStrategy"
                 p:objectMapper-ref="shibboleth.oidc.JSONObjectMapper" />
         </property>
+        <property name="activationCondition">
+            <bean parent="shibboleth.Conditions.Expression"
+                c:expression="#input.ensureInboundMessageContext().containsSubcontext(T(net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl.RelyingPartyTrustChainContext))" />
+        </property>
     </bean>
 
     <bean id="RelyingPartyTrustChainContextLookupStrategy" parent="shibboleth.Functions.Expression"
@@ -305,7 +304,7 @@
         class="net.shibboleth.idp.plugin.oidc.op.profile.impl.BuildRegistrationErrorResponseFromEvent"
         scope="prototype"
         p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier"
-        p:mappedErrors="#{getObject('shibboleth.oidc.register.MappedErrors') ?: getObject('shibboleth.oidc.register.DefaultMappedErrors')}">
+        p:mappedErrors="#{getObject('shibboleth.oidfed.register.MappedErrors') ?: getObject('shibboleth.oidfed.register.DefaultMappedErrors')}">
         <property name="eventContextLookupStrategy">
             <bean
                 class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
index 6d987a4..387b78e 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
@@ -65,14 +65,14 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
     public void testInvalidContentType() throws Exception {
         setJsonRequest("POST", "{}");
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertErrorCode(result, "invalid_client_metadata");
+        assertErrorCode(result, "invalid_request");
     }
 
     @Test
     public void testEmptyEntityConfiguration() throws Exception {
         setRequest("POST", "", "application/entity-statement+jwt");
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertErrorCode(result, "invalid_client_metadata");
+        assertErrorCode(result, "invalid_request");
     }
 
     @Test
@@ -96,7 +96,7 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
         rpConfigureMockHttpClient(clientId);
         setRequest("POST", rpEntityConfiguration(clientId), "application/json");
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertErrorCode(result, "invalid_client_metadata");
+        assertErrorCode(result, "invalid_request");
     }
 
     @Test
@@ -131,7 +131,7 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         verify(federationHttpClient, times(0)).executeOpen(any(),
                 argThat(new RequestUriMatcher(entityConfigurationUrl(clientId))), any());
-        assertErrorCode(result, "invalid_request");
+        assertErrorCode(result, "invalid_client");
     }
 
     @Test
@@ -143,7 +143,7 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
         verify(federationHttpClient, times(0)).executeOpen(any(),
                 argThat(new RequestUriMatcher(entityConfigurationUrl(clientId))), any());
-        assertErrorCode(result, "invalid_request");
+        assertErrorCode(result, "invalid_client");
     }
 
     @Test

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


More information about the commits mailing list