[java-idp-oidc] 03/04: JOIDC-256 - Facilitate extending the default set of mapped error responses

Henri Mikkonen henri.mikkonen at iki.fi
Mon Sep 8 10:53:15 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-oidc.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=2741d8b767c688d93b19750b16b54643db8a2b0d

commit 2741d8b767c688d93b19750b16b54643db8a2b0d
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Mon Sep 8 13:50:27 2025 +0300

    JOIDC-256 - Facilitate extending the default set of mapped error responses
    
    https://shibboleth.atlassian.net/browse/JOIDC-256
    
    Add flow/endpoint-specific classes that are automatically used as the default event to error mapping:
    
    - oauth2/introspection: IntrospectionErrorObjectMapping
    - oauth2/pushed-authorization: PushedAuthorizationErrorObjectMapping
    - oauth2/revocation: RevocationErrorObjectMapping
    - oidc/authorize: AuthorizationErrorObjectMapping
    - oidc/regiter: RegistrationErrorObjectMapping
    - oidc/token: TokenErrorObjectMapping
    - oidc/userinfo: UserInfoErrorObjectMapping
    
    Each class has a corresponding abstract global bean, named with the 'shibboleth.oidc.' -prefix. The new default mappings can be wired in the following way:
    
        <bean parent="shibboleth.oidc.AuthorizationErrorMapping"
            p:eventId="CustomEventId">
            <property name="errorObject">
                <bean class="com.nimbusds.oauth2.sdk.ErrorObject" c:_0="custom_authorization_error_code" c:_1="Custom description" c:_2="400" />
            </property>
        </bean>
---
 .../op/profile/AbstractErrorObjectMapping.java     | 87 ++++++++++++++++++++++
 .../profile/AuthorizationErrorObjectMapping.java   | 24 ++++++
 .../op/profile/EventIdToErrorObjectMapping.java    | 41 ++++++++++
 .../profile/IntrospectionErrorObjectMapping.java   | 24 ++++++
 .../PushedAuthorizationErrorObjectMapping.java     | 24 ++++++
 .../op/profile/RegistrationErrorObjectMapping.java | 24 ++++++
 .../op/profile/RevocationErrorObjectMapping.java   | 24 ++++++
 .../oidc/op/profile/TokenErrorObjectMapping.java   | 24 ++++++
 .../op/profile/UserInfoErrorObjectMapping.java     | 24 ++++++
 .../BuildIntrospectionErrorResponseFromEvent.java  | 20 ++++-
 ...dPushedAuthorizationErrorResponseFromEvent.java | 22 +++++-
 .../BuildRevokeTokenErrorResponseFromEvent.java    | 18 ++++-
 .../impl/AbstractBuildErrorResponseFromEvent.java  | 35 +++++++--
 .../BuildAuthenticationErrorResponseFromEvent.java | 13 +++-
 .../BuildRegistrationErrorResponseFromEvent.java   | 20 ++++-
 .../impl/BuildTokenErrorResponseFromEvent.java     | 20 ++++-
 .../impl/BuildUserInfoErrorResponseFromEvent.java  | 16 +++-
 .../META-INF/net.shibboleth.idp/postconfig.xml     | 28 +++++++
 18 files changed, 474 insertions(+), 14 deletions(-)

diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/AbstractErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/AbstractErrorObjectMapping.java
new file mode 100644
index 00000000..6e1ddba7
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/AbstractErrorObjectMapping.java
@@ -0,0 +1,87 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+import javax.annotation.Nonnull;
+
+import com.nimbusds.oauth2.sdk.ErrorObject;
+
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * A base class for classes implementing {@link EventIdToErrorObjectMapping}.
+ * 
+ * @since 4.4.0
+ */
+public class AbstractErrorObjectMapping extends AbstractIdentifiableInitializableComponent
+    implements EventIdToErrorObjectMapping {
+
+    /** Event ID for the error object mapping. */
+    @NonnullAfterInit @NotEmpty private String eventId;
+
+    /** Error object mapped to the event ID. */
+    @NonnullAfterInit private ErrorObject errorObject;
+
+    /** {@inheritDoc} */
+    @Override
+    protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+        
+        if (StringSupport.trimOrNull(eventId) == null) {
+            throw new ComponentInitializationException("EventId cannot be null");
+        }
+        if (errorObject == null) {
+            throw new ComponentInitializationException("ErrorObject cannot be null");
+        }
+    }
+
+    /**
+     * Set event ID for the error object mapping.
+     * 
+     * @param id event id
+     */
+    public void setEventId(@Nonnull @NotEmpty final String id) {
+        checkSetterPreconditions();
+        eventId = Constraint.isNotNull(StringSupport.trimOrNull(id), "EventId cannot be null");
+    }
+    
+    /** {@inheritDoc} */
+    @Override @Nonnull @NotEmpty public String getEventId() {
+        checkComponentActive();
+        return eventId;
+    }
+
+    /**
+     * Set error object mapped to the event ID.
+     * 
+     * @param error error object
+     */
+    public void setErrorObject(@Nonnull final ErrorObject error) {
+        checkSetterPreconditions();
+        errorObject = Constraint.isNotNull(error, "ErrorObject cannot be null");
+    }
+    /** {@inheritDoc} */
+    @Override @Nonnull
+    public ErrorObject getErrorObject() {
+        checkComponentActive();
+        return errorObject;
+    }
+
+}
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/AuthorizationErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/AuthorizationErrorObjectMapping.java
new file mode 100644
index 00000000..65bf14ee
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/AuthorizationErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to authentication requests.
+ * 
+ * @since 4.4.0
+ */
+public class AuthorizationErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/EventIdToErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/EventIdToErrorObjectMapping.java
new file mode 100644
index 00000000..1e787d2c
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/EventIdToErrorObjectMapping.java
@@ -0,0 +1,41 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+import javax.annotation.Nonnull;
+
+import com.nimbusds.oauth2.sdk.ErrorObject;
+
+/**
+ * Interface for mapping an event ID to an Nimbus error object.
+ * 
+ * @since 4.4.0
+ */
+public interface EventIdToErrorObjectMapping {
+
+    /**
+     * Get the event ID for the error object mapping.
+     * 
+     * @return event id
+     */
+    @Nonnull public String getEventId();
+
+    /**
+     * Get the error object mapped to the event ID.
+     * 
+     * @return error object
+     */
+    @Nonnull public ErrorObject getErrorObject();
+}
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/IntrospectionErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/IntrospectionErrorObjectMapping.java
new file mode 100644
index 00000000..88c397b5
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/IntrospectionErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to token introspection.
+ * 
+ * @since 4.4.0
+ */
+public class IntrospectionErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/PushedAuthorizationErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/PushedAuthorizationErrorObjectMapping.java
new file mode 100644
index 00000000..b2754d1e
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/PushedAuthorizationErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to pushed authorization requests.
+ * 
+ * @since 4.4.0
+ */
+public class PushedAuthorizationErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/RegistrationErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/RegistrationErrorObjectMapping.java
new file mode 100644
index 00000000..369ea293
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/RegistrationErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to dynamic registration.
+ * 
+ * @since 4.4.0
+ */
+public class RegistrationErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/RevocationErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/RevocationErrorObjectMapping.java
new file mode 100644
index 00000000..1349e012
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/RevocationErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to token revocation.
+ * 
+ * @since 4.4.0
+ */
+public class RevocationErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/TokenErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/TokenErrorObjectMapping.java
new file mode 100644
index 00000000..858bf768
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/TokenErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to token endpoint.
+ * 
+ * @since 4.4.0
+ */
+public class TokenErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/UserInfoErrorObjectMapping.java b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/UserInfoErrorObjectMapping.java
new file mode 100644
index 00000000..d836c523
--- /dev/null
+++ b/idp-oidc-extension-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/UserInfoErrorObjectMapping.java
@@ -0,0 +1,24 @@
+/*
+ * 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.idp.plugin.oidc.op.profile;
+
+/**
+ * An error mapping related to user info.
+ * 
+ * @since 4.4.0
+ */
+public class UserInfoErrorObjectMapping extends AbstractErrorObjectMapping {
+
+}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildIntrospectionErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildIntrospectionErrorResponseFromEvent.java
index 5e8f4458..c734fc4f 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildIntrospectionErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildIntrospectionErrorResponseFromEvent.java
@@ -14,11 +14,18 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.beans.factory.annotation.Autowired;
+
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.TokenIntrospectionErrorResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.IntrospectionErrorObjectMapping;
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponseFromEvent;
 
 /**
@@ -26,7 +33,18 @@ import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponse
  * Introspection error response message and attaches it as the outbound message.
  */
 public class BuildIntrospectionErrorResponseFromEvent
-        extends AbstractBuildErrorResponseFromEvent<TokenIntrospectionErrorResponse> {
+        extends AbstractBuildErrorResponseFromEvent<TokenIntrospectionErrorResponse, IntrospectionErrorObjectMapping> {
+
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    @Autowired
+    public BuildIntrospectionErrorResponseFromEvent(
+            @Nullable final Collection<IntrospectionErrorObjectMapping> freeObjects) {
+        super(freeObjects);
+    }
 
     @Override
     protected TokenIntrospectionErrorResponse buildErrorResponse(final ErrorObject error,
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildPushedAuthorizationErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildPushedAuthorizationErrorResponseFromEvent.java
index ce0ae85c..a9082bbd 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildPushedAuthorizationErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildPushedAuthorizationErrorResponseFromEvent.java
@@ -14,19 +14,37 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.beans.factory.annotation.Autowired;
+
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.PushedAuthorizationErrorResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.PushedAuthorizationErrorObjectMapping;
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponseFromEvent;
 
 /**
  * This action reads an event from the configured {@link EventContext} lookup strategy, constructs an OAuth2 Token
  * PAR error response message and attaches it as the outbound message.
  */
-public class BuildPushedAuthorizationErrorResponseFromEvent
-        extends AbstractBuildErrorResponseFromEvent<PushedAuthorizationErrorResponse> {
+public class BuildPushedAuthorizationErrorResponseFromEvent extends AbstractBuildErrorResponseFromEvent
+        <PushedAuthorizationErrorResponse, PushedAuthorizationErrorObjectMapping> {
+
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    @Autowired
+    public BuildPushedAuthorizationErrorResponseFromEvent(
+            @Nullable final Collection<PushedAuthorizationErrorObjectMapping> freeObjects) {
+        super(freeObjects);
+    }
 
     @Override
     protected PushedAuthorizationErrorResponse buildErrorResponse(final ErrorObject error,
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java
index 7f747795..76e4dbc8 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oauth2/profile/impl/BuildRevokeTokenErrorResponseFromEvent.java
@@ -14,14 +14,19 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oauth2.profile.impl;
 
+import java.util.Collection;
+
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import com.nimbusds.oauth2.sdk.ErrorObject;
 
 import net.shibboleth.idp.plugin.oidc.op.oauth2.messaging.impl.OAuth2RevocationErrorResponse;
+import net.shibboleth.idp.plugin.oidc.op.profile.RevocationErrorObjectMapping;
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponseFromEvent;
 
 /**
@@ -29,7 +34,18 @@ import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponse
  * Revocation error response message and attaches it as the outbound message.
  */
 public class BuildRevokeTokenErrorResponseFromEvent
-        extends AbstractBuildErrorResponseFromEvent<OAuth2RevocationErrorResponse> {
+        extends AbstractBuildErrorResponseFromEvent<OAuth2RevocationErrorResponse, RevocationErrorObjectMapping> {
+
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    @Autowired
+    public BuildRevokeTokenErrorResponseFromEvent(
+            @Nullable final Collection<RevocationErrorObjectMapping> freeObjects) {
+        super(freeObjects);
+    }
 
     @Override
     protected OAuth2RevocationErrorResponse buildErrorResponse(@Nonnull final ErrorObject error,
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
index 34242961..db1a7d18 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/AbstractBuildErrorResponseFromEvent.java
@@ -14,11 +14,14 @@
 
 package net.shibboleth.idp.plugin.oidc.op.profile.impl;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -29,7 +32,9 @@ import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.ErrorResponse;
 import com.nimbusds.oauth2.sdk.http.HTTPResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.EventIdToErrorObjectMapping;
 import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
@@ -39,8 +44,10 @@ import net.shibboleth.shared.primitive.LoggerFactory;
  * message context was found.
  * 
  * @param <T> ErrorResponse implementation.
+ * @param <M> Type of {@link EventIdToErrorObjectMapping} that are autowired by the extending classes.
  */
-public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorResponse> extends AbstractProfileAction {
+public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorResponse,
+    M extends EventIdToErrorObjectMapping> extends AbstractProfileAction {
     
     /** Default value for the error code in the error response messages. */
     public static final String DEFAULT_ERROR_CODE = "invalid_request";
@@ -65,12 +72,21 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
     /** The code for unmapped events. */
     private String defaultCode;
 
-    /** Constructor. */
-    public AbstractBuildErrorResponseFromEvent() {
+    /** The autowired error object mappings. */
+    @Nonnull private Collection<M> autowiredMappings;
+
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    public AbstractBuildErrorResponseFromEvent(@Nullable final Collection<M> freeObjects) {
         eventContextLookupStrategy = new CurrentOrPreviousEventLookup();
         mappedErrors = new HashMap<>();
         defaultStatusCode = DEFAULT_HTTP_STATUS_CODE;
         defaultCode = DEFAULT_ERROR_CODE;
+        autowiredMappings =
+                freeObjects != null ? CollectionSupport.copyToList(freeObjects) : CollectionSupport.emptyList();
     }
 
     /**
@@ -156,8 +172,17 @@ public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorRespons
             log.debug("{} Found mapped event for {}", getLogPrefix(), eventValue);
             error = mappedErrors.get(eventValue);
         } else {
-            log.debug("{} No mapped event found for {}, creating general {}", getLogPrefix(), eventValue, defaultCode);
-            error = new ErrorObject(defaultCode, eventValue, defaultStatusCode);
+            final Optional<M> mapping = autowiredMappings.stream()
+                    .filter(m -> eventValue.equals(m.getEventId()))
+                    .findFirst();
+            if (mapping.isPresent()) {
+                log.debug("{} Found autowired mapping for {}", getLogPrefix(), eventValue);
+                error = mapping.get().getErrorObject();
+            } else {
+                log.debug("{} No mapped event found for {}, creating general {}", getLogPrefix(), eventValue,
+                        defaultCode);
+                error = new ErrorObject(defaultCode, eventValue, defaultStatusCode);
+            }
         }
         assert error != null;
         final ErrorResponse errorResponse = buildErrorResponse(error, profileRequestContext);
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildAuthenticationErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildAuthenticationErrorResponseFromEvent.java
index 0c9dc605..411fba94 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildAuthenticationErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildAuthenticationErrorResponseFromEvent.java
@@ -15,15 +15,18 @@
 package net.shibboleth.idp.plugin.oidc.op.profile.impl;
 
 import java.net.URI;
+import java.util.Collection;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.ResponseMode;
@@ -32,6 +35,7 @@ import com.nimbusds.oauth2.sdk.id.Issuer;
 import com.nimbusds.oauth2.sdk.id.State;
 import com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.AuthorizationErrorObjectMapping;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.ValidatedRedirectURILookupFunction;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.oidc.profile.config.logic.IncludeIssuerInAuthenticationResponsePredicate;
@@ -47,7 +51,7 @@ import net.shibboleth.shared.primitive.StringSupport;
  * authentication error response message and attaches it as the outbound message.
  */
 public class BuildAuthenticationErrorResponseFromEvent
-        extends AbstractBuildErrorResponseFromEvent<AuthenticationErrorResponse> {
+        extends AbstractBuildErrorResponseFromEvent<AuthenticationErrorResponse, AuthorizationErrorObjectMapping> {
 
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(BuildAuthenticationErrorResponseFromEvent.class);
@@ -72,8 +76,13 @@ public class BuildAuthenticationErrorResponseFromEvent
 
     /**
      * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
      */
-    public BuildAuthenticationErrorResponseFromEvent() {
+    @Autowired
+    public BuildAuthenticationErrorResponseFromEvent(
+            @Nullable final Collection<AuthorizationErrorObjectMapping> freeObjects) {
+        super(freeObjects);
         issuerLookupStrategy = new IssuerLookupFunction();
         includeIssuerInResponsePredicate = new IncludeIssuerInAuthenticationResponsePredicate();
     }
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildRegistrationErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildRegistrationErrorResponseFromEvent.java
index 7f9c3c5c..c4ef5206 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildRegistrationErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildRegistrationErrorResponseFromEvent.java
@@ -14,18 +14,36 @@
 
 package net.shibboleth.idp.plugin.oidc.op.profile.impl;
 
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.client.ClientRegistrationErrorResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.RegistrationErrorObjectMapping;
+
 /**
  * This action reads an event from the configured {@link EventContext} lookup strategy, constructs an OIDC client
  * registration error response message and attaches it as the outbound message.
  */
 public class BuildRegistrationErrorResponseFromEvent
-        extends AbstractBuildErrorResponseFromEvent<ClientRegistrationErrorResponse> {
+        extends AbstractBuildErrorResponseFromEvent<ClientRegistrationErrorResponse, RegistrationErrorObjectMapping> {
+
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    @Autowired
+    public BuildRegistrationErrorResponseFromEvent(
+            @Nullable final Collection<RegistrationErrorObjectMapping> freeObjects) {
+        super(freeObjects);
+    }
 
     /** {@inheritDoc} */
     @Override
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildTokenErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildTokenErrorResponseFromEvent.java
index 51f7ef61..ed316d64 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildTokenErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/BuildTokenErrorResponseFromEvent.java
@@ -14,17 +14,35 @@
 
 package net.shibboleth.idp.plugin.oidc.op.profile.impl;
 
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.TokenErrorResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.TokenErrorObjectMapping;
+
 /**
  * This action reads an event from the configured {@link EventContext} lookup strategy, constructs an OIDC token error
  * response message and attaches it as the outbound message.
  */
-public class BuildTokenErrorResponseFromEvent extends AbstractBuildErrorResponseFromEvent<TokenErrorResponse> {
+public class BuildTokenErrorResponseFromEvent
+        extends AbstractBuildErrorResponseFromEvent<TokenErrorResponse, TokenErrorObjectMapping> {
+
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    @Autowired
+    public BuildTokenErrorResponseFromEvent(@Nullable final Collection<TokenErrorObjectMapping> freeObjects) {
+        super(freeObjects);
+    }
 
     /** {@inheritDoc} */
     @Override
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/userinfo/profile/impl/BuildUserInfoErrorResponseFromEvent.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/userinfo/profile/impl/BuildUserInfoErrorResponseFromEvent.java
index 40d9e082..ca6bbb7e 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/userinfo/profile/impl/BuildUserInfoErrorResponseFromEvent.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/userinfo/profile/impl/BuildUserInfoErrorResponseFromEvent.java
@@ -21,17 +21,20 @@ import java.util.Set;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.profile.context.EventContext;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.xmlsec.algorithm.AlgorithmSupport;
 import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.oauth2.sdk.ErrorObject;
 import com.nimbusds.oauth2.sdk.token.DPoPTokenError;
 import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
 
+import net.shibboleth.idp.plugin.oidc.op.profile.UserInfoErrorObjectMapping;
 import net.shibboleth.idp.plugin.oidc.op.profile.impl.AbstractBuildErrorResponseFromEvent;
 import net.shibboleth.oidc.security.jose.SignatureValidationParameters;
 import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
@@ -46,7 +49,8 @@ import net.shibboleth.shared.primitive.StringSupport;
  * This action reads an event from the configured {@link EventContext} lookup strategy, constructs an OIDC user info
  * error response message and attaches it as the outbound message.
  */
-public class BuildUserInfoErrorResponseFromEvent extends AbstractBuildErrorResponseFromEvent<UserInfoErrorResponse> {
+public class BuildUserInfoErrorResponseFromEvent
+        extends AbstractBuildErrorResponseFromEvent<UserInfoErrorResponse, UserInfoErrorObjectMapping> {
 
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(BuildUserInfoErrorResponseFromEvent.class);
@@ -58,6 +62,16 @@ public class BuildUserInfoErrorResponseFromEvent extends AbstractBuildErrorRespo
     /** Algorithm candidates to be verified against the security configuration. */
     @NonnullAfterInit private List<JWSAlgorithm> algorithmCandidates;
 
+    /**
+     * Constructor.
+     *
+     * @param freeObjects free-standing objects to add
+     */
+    @Autowired
+    public BuildUserInfoErrorResponseFromEvent(@Nullable final Collection<UserInfoErrorObjectMapping> freeObjects) {
+        super(freeObjects);
+    }
+
     /**
      * Set the strategy used to look up the {@link SecurityParametersContext} to set the parameters for.
      * 
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index a92f3748..0bd7dc9c 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -899,4 +899,32 @@
     <bean id="shibboleth.oidc.MetadataLookupExtensionFlow" abstract="true"
         class="net.shibboleth.idp.plugin.oidc.op.metadata.MetadataLookupExtensionFlowDescriptor" />
 
+   <bean id="shibboleth.oidc.AuthorizationErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.AuthorizationErrorObjectMapping"
+       abstract="true" />
+
+   <bean id="shibboleth.oidc.PushedAuthorizationErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.PushedAuthorizationErrorObjectMapping"
+       abstract="true" />
+
+   <bean id="shibboleth.oidc.RegistrationErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.RegistrationErrorObjectMapping"
+       abstract="true" />
+
+   <bean id="shibboleth.oidc.TokenErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.TokenErrorObjectMapping"
+       abstract="true" />
+
+   <bean id="shibboleth.oidc.UserInfoErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.UserInfoErrorObjectMapping"
+       abstract="true" />
+
+   <bean id="shibboleth.oidc.IntrospectionErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.IntrospectionErrorObjectMapping"
+       abstract="true" />
+
+   <bean id="shibboleth.oidc.RevocationErrorMapping"
+       class="net.shibboleth.idp.plugin.oidc.op.profile.RevocationErrorObjectMapping"
+       abstract="true" />
+
 </beans>

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


More information about the commits mailing list