[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