[java-oidc-common] branch main updated: JCOMOIDC-38 - Move various support classes from the OP plugin

Phil Smart philip.smart at jisc.ac.uk
Thu Nov 24 15:41:15 UTC 2022


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

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

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=2116d701bc17b62b0df9fd20326bf4ae7eb50bb1

The following commit(s) were added to refs/heads/main by this push:
     new 2116d70  JCOMOIDC-38 - Move various support classes from the OP plugin
2116d70 is described below

commit 2116d701bc17b62b0df9fd20326bf4ae7eb50bb1
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Thu Nov 24 15:41:12 2022 +0000

    JCOMOIDC-38 - Move various support classes from the OP plugin
    
     - Move the JSON response builders and model objects
    
    https://shibboleth.atlassian.net/browse/JCOMOIDC-38
---
 .../oidc/profile/messaging/JSONErrorResponse.java  | 113 ++++++++++++++
 .../profile/messaging/JSONSuccessResponse.java     |  98 ++++++++++++
 .../oidc/profile/messaging/package-info.java       |  21 +++
 .../impl/AbstractBuildErrorResponseFromEvent.java  | 171 +++++++++++++++++++++
 .../impl/BuildJSONErrorResponseFromEvent.java      |  40 +++++
 5 files changed, 443 insertions(+)

diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/JSONErrorResponse.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/JSONErrorResponse.java
new file mode 100644
index 0000000..553a8ee
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/JSONErrorResponse.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.oidc.profile.messaging;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.nimbusds.common.contenttype.ContentType;
+import com.nimbusds.oauth2.sdk.ErrorObject;
+import com.nimbusds.oauth2.sdk.ErrorResponse;
+import com.nimbusds.oauth2.sdk.http.HTTPResponse;
+
+import net.minidev.json.JSONObject;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/** Class for creating JSON Error response for requests expecting JSON response. */
+public class JSONErrorResponse implements ErrorResponse {
+
+    /** Error object. */
+    private ErrorObject error;
+
+    /** cache control value. */
+    private String cacheControl;
+
+    /** pragma value. */
+    private String pragma;
+
+    /**
+     * Constructor.
+     * 
+     * @param errorObject error. MUST not be null.
+     */
+    public JSONErrorResponse(@Nonnull final ErrorObject errorObject) {
+        this(errorObject, null, null);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param errorObject JSON content.
+     * @param cacheControlValue cache control value.
+     * @param pragmaValue pragma value.
+     */
+    public JSONErrorResponse(@Nonnull final ErrorObject errorObject, @Nullable final String cacheControlValue,
+            @Nullable final String pragmaValue) {
+        Constraint.isNotNull(errorObject, "content cannot be null");
+        error = errorObject;
+        cacheControl = cacheControlValue;
+        pragma = pragmaValue;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean indicatesSuccess() {
+        return true;
+    }
+
+    /**
+     * Error content as json.
+     * 
+     * @return error as json.
+     */
+    private String getContent() {
+        final JSONObject content = new JSONObject();
+        if (error == null) {
+            return null;
+        }
+        content.put("error", error.getCode());
+        if (error.getDescription() != null) {
+            content.put("error_description", error.getDescription());
+        }
+        if (error.getURI() != null) {
+            content.put("error_uri", error.getURI().toString());
+        }
+        return content.toString();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public HTTPResponse toHTTPResponse() {
+        final HTTPResponse httpResponse = new HTTPResponse(error.getHTTPStatusCode());
+        httpResponse.setEntityContentType(ContentType.APPLICATION_JSON);
+        if (cacheControl != null) {
+            httpResponse.setCacheControl(cacheControl);
+        }
+        if (pragma != null) {
+            httpResponse.setPragma(pragma);
+        }
+        httpResponse.setContent(getContent());
+        return httpResponse;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ErrorObject getErrorObject() {
+        return error;
+    }
+}
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/JSONSuccessResponse.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/JSONSuccessResponse.java
new file mode 100644
index 0000000..184a1fc
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/JSONSuccessResponse.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.oidc.profile.messaging;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.base.MoreObjects;
+import com.nimbusds.common.contenttype.ContentType;
+import com.nimbusds.oauth2.sdk.SuccessResponse;
+import com.nimbusds.oauth2.sdk.http.HTTPResponse;
+
+import net.minidev.json.JSONObject;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/** Class for creating JSON Success response. */
+public class JSONSuccessResponse implements SuccessResponse {
+
+    /** JSON content. */
+    private JSONObject content;
+
+    /** cache control value. */
+    private String cacheControl;
+
+    /** pragma value. */
+    private String pragma;
+
+    /**
+     * Constructor.
+     * 
+     * @param contentObject JSON content. MUST not be null.
+     */
+    public JSONSuccessResponse(@Nonnull final JSONObject contentObject) {
+        this(contentObject, null, null);
+
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param contentObject JSON content
+     * @param cacheControlValue cache control value
+     * @param pragmaValue pragma value
+     */
+    public JSONSuccessResponse(@Nonnull final JSONObject contentObject, @Nullable final String cacheControlValue,
+            @Nullable final String pragmaValue) {
+        Constraint.isNotNull(contentObject, "content cannot be null");
+        content = contentObject;
+        cacheControl = cacheControlValue;
+        pragma = pragmaValue;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean indicatesSuccess() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).omitNullValues()
+                .add("content", content.toJSONString())
+                .add("cacheControl", cacheControl)
+                .add("pragma", pragma)
+                .toString();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public HTTPResponse toHTTPResponse() {
+        final HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK);
+        httpResponse.setEntityContentType(ContentType.APPLICATION_JSON);
+        if (cacheControl != null) {
+            httpResponse.setCacheControl(cacheControl);
+        }
+        if (pragma != null) {
+            httpResponse.setPragma(pragma);
+        }
+        httpResponse.setContent(content.toJSONString());
+        return httpResponse;
+    }
+}
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/package-info.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/package-info.java
new file mode 100644
index 0000000..76cd287
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/messaging/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.
+ */
+
+/**
+ * OIDC messaging interfaces and classes.
+ */
+package net.shibboleth.oidc.profile.messaging;
\ No newline at end of file
diff --git a/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/AbstractBuildErrorResponseFromEvent.java b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/AbstractBuildErrorResponseFromEvent.java
new file mode 100644
index 0000000..ea0f7d3
--- /dev/null
+++ b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/AbstractBuildErrorResponseFromEvent.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.oidc.profile.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.EventContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.CurrentOrPreviousEventLookup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.nimbusds.oauth2.sdk.ErrorObject;
+import com.nimbusds.oauth2.sdk.ErrorResponse;
+import com.nimbusds.oauth2.sdk.http.HTTPResponse;
+
+import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * This action is extended by error response actions. Action reads an event from the configured {@link EventContext}
+ * lookup strategy, constructs an OIDC error response message and attaches it as the outbound message, if outbound
+ * message context was found.
+ * 
+ * @param <T> ErrorResponse implementation.
+ */
+public abstract class AbstractBuildErrorResponseFromEvent<T extends ErrorResponse> extends AbstractProfileAction {
+    
+    /** Default value for the error code in the error response messages. */
+    public static final String DEFAULT_ERROR_CODE = "invalid_request";
+    
+    /** Default value for the HTTP response status code in the HTTP responses. */
+    public static final int DEFAULT_HTTP_STATUS_CODE = HTTPResponse.SC_BAD_REQUEST;
+
+    /** Class logger. */
+    @Nonnull
+    private final Logger log = LoggerFactory.getLogger(AbstractBuildErrorResponseFromEvent.class);
+
+    /** Strategy function for access to {@link EventContext} to check. */
+    @Nonnull
+    private Function<ProfileRequestContext, EventContext> eventContextLookupStrategy;
+
+    /** Map of eventIds to pre-configured error objects. */
+    private Map<String, ErrorObject> mappedErrors;
+
+    /** The status code for unmapped events. */
+    private int defaultStatusCode;
+
+    /** The code for unmapped events. */
+    private String defaultCode;
+
+    /** Constructor. */
+    public AbstractBuildErrorResponseFromEvent() {
+        eventContextLookupStrategy = new CurrentOrPreviousEventLookup();
+        mappedErrors = new HashMap<>();
+        defaultStatusCode = DEFAULT_HTTP_STATUS_CODE;
+        defaultCode = DEFAULT_ERROR_CODE;
+    }
+
+    /**
+     * Set the status code for unmapped events.
+     * 
+     * @param code The default status code for unmapped events.
+     */
+    public void setDefaultStatusCode(final int code) {
+        defaultStatusCode = code;
+    }
+
+    /**
+     * Set the code for unmapped events.
+     * 
+     * @param code The default status code for unmapped events.
+     */
+    public void setDefaultCode(@Nonnull final String code) {
+        defaultCode = Constraint.isNotNull(code, "Default code cannot be null");
+    }
+
+    /**
+     * Set lookup strategy for {@link EventContext} to check.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setEventContextLookupStrategy(@Nonnull final Function<ProfileRequestContext, EventContext> strategy) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        eventContextLookupStrategy = Constraint.isNotNull(strategy, "EventContext lookup strategy cannot be null");
+    }
+
+    /**
+     * Set map of eventIds to pre-configured error objects.
+     * 
+     * @param errors map of eventIds to pre-configured error objects.
+     */
+    public void setMappedErrors(@Nonnull final Map<String, ErrorObject> errors) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        mappedErrors = Constraint.isNotNull(errors, "Mapped errors cannot be null");
+    }
+
+    /**
+     * Method implemented by the extending class to create ErrorResponse.
+     * 
+     * @param error error object to build the response from.
+     * @param profileRequestContext profile request context.
+     * @return ErrorResponse
+     */
+    protected abstract T buildErrorResponse(ErrorObject error, ProfileRequestContext profileRequestContext);
+    
+    /** {@inheritDoc} */
+    @Override
+    protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+        
+        if (!super.doPreExecute(profileRequestContext)) {
+            return false;
+        }
+        
+        if (profileRequestContext.getOutboundMessageContext() == null) {
+            log.debug("{} No outbound message context initialized, nothing to do", getLogPrefix());
+            return false;
+        }
+        
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+        final EventContext eventCtx = eventContextLookupStrategy.apply(profileRequestContext);
+        if (eventCtx == null || eventCtx.getEvent() == null) {
+            log.error("{} No event to be included in the response, nothing to do", getLogPrefix());
+            return;
+        }
+        final String event = eventCtx.getEvent().toString();
+        final ErrorObject error;
+        if (mappedErrors.containsKey(event)) {
+            log.debug("{} Found mapped event for {}", getLogPrefix(), event);
+            error = mappedErrors.get(event);
+        } else {
+            log.debug("{} No mapped event found for {}, creating general {}", getLogPrefix(), event, defaultCode);
+            error = new ErrorObject(defaultCode, eventCtx.getEvent().toString(), defaultStatusCode);
+        }
+        final ErrorResponse errorResponse = buildErrorResponse(error, profileRequestContext);
+        if (errorResponse != null) {
+            profileRequestContext.getOutboundMessageContext()
+                    .setMessage(buildErrorResponse(error, profileRequestContext));
+            log.debug("{} ErrorResponse successfully set as the outbound message", getLogPrefix());
+        } else {
+            log.debug("{} Error response not formed", getLogPrefix());
+        }
+    }
+}
diff --git a/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/BuildJSONErrorResponseFromEvent.java b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/BuildJSONErrorResponseFromEvent.java
new file mode 100644
index 0000000..8203084
--- /dev/null
+++ b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/BuildJSONErrorResponseFromEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.oidc.profile.impl;
+
+import org.opensaml.profile.context.EventContext;
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import com.nimbusds.oauth2.sdk.ErrorObject;
+
+import net.shibboleth.oidc.profile.messaging.JSONErrorResponse;
+
+/**
+ * This action reads an event from the configured {@link EventContext} lookup strategy, constructs a json error response
+ * message and attaches it as the outbound message.
+ */
+public class BuildJSONErrorResponseFromEvent extends AbstractBuildErrorResponseFromEvent<JSONErrorResponse> {
+
+    /** {@inheritDoc} */
+    @Override
+    protected JSONErrorResponse buildErrorResponse(final ErrorObject error,
+            final ProfileRequestContext profileRequestContext) {
+        return new JSONErrorResponse(error);
+    }
+
+}

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


More information about the commits mailing list