[java-idp-plugin-oidc-op-oidfed] 02/02: Refactoring for metadata caches related to remote entity resolver and trust marks.
Codeberg
noreply at shibboleth.net
Wed Dec 17 13:47:19 UTC 2025
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/CACHE-REFACTOR
in repository java-idp-plugin-oidc-op-oidfed.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-oidc-op-oidfed/commit/154625d98fe5a81200139fdec1833629326f04f9
commit 154625d98fe5a81200139fdec1833629326f04f9
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Dec 17 15:46:45 2025 +0200
Refactoring for metadata caches related to remote entity resolver and trust marks.
- Harmonised them with the caches related to other fetched entity statements
- Request/Response are not using Nimbus interfaces anymore
- Syntax validation via Jackson object mapper
- Content validation during metadata filtering
---
.../op/oidfed/metadata/ResolveEntityResponse.java | 60 ++++++
.../metadata/ResolveEntityResponsePayload.java | 86 ++++++++
.../plugin/oidc/op/oidfed/metadata/TrustMark.java | 60 ++++++
.../oidc/op/oidfed/metadata/TrustMarkPayload.java | 126 ++++++++++++
.../oidc/op/oidfed/metadata/TrustMarkStatus.java | 60 ++++++
.../op/oidfed/metadata/TrustMarkStatusPayload.java | 80 ++++++++
.../oidfed/messaging/impl/TrustMarkResponse.java | 87 --------
.../messaging/impl/TrustMarkStatusRequest.java | 72 -------
.../messaging/impl/TrustMarkStatusResponse.java | 87 --------
...FederationEndpointResponseFetchingStrategy.java | 194 ------------------
...yResponseSignatureValidationFilterStrategy.java | 129 ------------
...ultResolveEntityTrustChainFetchingStrategy.java | 122 ------------
.../metadata/DefaultTrustMarkFetchingStrategy.java | 114 -----------
...kResponseSignatureValidationFilterStrategy.java | 129 ------------
.../DefaultTrustMarkStatusFetchingStrategy.java | 113 -----------
.../op/oidfed/metadata/EntityStatementHelper.java | 8 +-
.../metadata/TrustMarkResponseContainer.java | 75 -------
.../metadata/TrustMarkStatusResponseContainer.java | 69 -------
...EntityStatementContentValidationCondition.java} | 21 +-
...atementValidationCriteriaSetLookupFunction.java | 113 +++++++++++
...ultResolveEntityTrustChainFetchingStrategy.java | 134 +++++++++++++
...emoteResolveEntityCacheContainerIdentifier.java | 143 +++++++++++++
...moteResolveEntityCacheIdentifierCriterion.java} | 34 ++--
.../RemoteResolveEntityResponseContainer.java | 69 +++++++
.../cache/tm/DefaultTrustMarkFetchingStrategy.java | 130 ++++++++++++
.../tm/DefaultTrustMarkStatusFetchingStrategy.java | 129 ++++++++++++
...stMarkValidationCriteriaSetLookupFunction.java} | 83 ++++----
.../cache/tm/RemoteTrustMarkContainer.java | 68 +++++++
.../cache/tm/RemoteTrustMarkStatusContainer.java | 68 +++++++
.../cache/tm/TrustMarkCacheIdentifier.java} | 57 +++---
.../tm/TrustMarkIdentifierCriterion.java} | 33 ++-
.../cache/tm/TrustMarkStatusCacheIdentifier.java | 103 ++++++++++
.../tm/TrustMarkStatusIdentifierCriterion.java} | 34 ++--
...efaultSubordinateStatementFetchingStrategy.java | 19 +-
...inateStatementSignatureValidationCondition.java | 116 -----------
.../oidfed/profile/impl/CallResolveEntityApi.java | 52 ++---
...TrustMarkFromMetadataCacheFetchingFunction.java | 27 +--
.../META-INF/net.shibboleth.idp/postconfig.xml | 221 +++++++++++++++++----
.../oidfed/metadata-lookup-ext-oidfed-beans.xml | 2 +-
.../idp/flows/oidfed/register/register-beans.xml | 2 +-
.../oidfed/resolve-entity/resolve-entity-beans.xml | 2 +-
.../flow/oidfed/EntityConfigurationFlowTest.java | 5 +-
42 files changed, 1796 insertions(+), 1540 deletions(-)
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
new file mode 100644
index 0000000..57d2cec
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponse.java
@@ -0,0 +1,60 @@
+/*
+ * 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.oidfed.metadata;
+
+import javax.annotation.Nonnull;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.shared.logic.ConstraintViolationException;
+
+/**
+ * A wrapper class extending {@link EntityStatement} with parsed claims related to resolve entity response.
+ */
+public class ResolveEntityResponse extends EntityStatement {
+
+ /**
+ * Constructor.
+ *
+ * @param signedJwt entity configuration
+ * @param payload entity configuration payload
+ * @throws ConstraintViolationException if the payload syntax/content is not expected
+ */
+ protected ResolveEntityResponse(@Nonnull final SignedJWT signedJwt,
+ @Nonnull final ResolveEntityResponsePayload payload)
+ throws ConstraintViolationException {
+ super(signedJwt, payload);
+ }
+
+ /**
+ * Parse an {@link ResolveEntityResponse} from the given JWT by using the given object mapper.
+ *
+ * @param jwt entity statement JWT
+ * @param objectMapper object mapper capable of parsing JWT payload
+ * @return entity configuration
+ * @throws JsonProcessingException if the payload could not be parsed
+ */
+ @Nonnull public static ResolveEntityResponse parse(@Nonnull final SignedJWT jwt,
+ @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
+ final JavaType objectType = objectMapper.constructType(ResolveEntityResponsePayload.class);
+ final ResolveEntityResponsePayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
+ assert result != null;
+ return new ResolveEntityResponse(jwt, result);
+ }
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponsePayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponsePayload.java
new file mode 100644
index 0000000..a3f7d5b
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ResolveEntityResponsePayload.java
@@ -0,0 +1,86 @@
+/*
+ * 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.oidfed.metadata;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Resolve Entity response payload claims as defined by the OpenID Federation 1.0 Section 8.3.2.
+ */
+public class ResolveEntityResponsePayload extends EntityStatementPayload {
+
+ /** An array containing the sequence of Entity Statements that compose the Trust Chain. */
+ @JsonProperty("trust_chain") private List<String> trustChain;
+
+ /** An array of Trust Marks. */
+ @JsonProperty("trust_marks") private List<Map<String,String>> trustMarks;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("iss", getIssuer())
+ .add("sub", getSubject())
+ .add("iat", getIssuedAt())
+ .add("exp", getExpiration())
+ .add("metadata", getMetadata())
+ .add("trust_chain", getTrustChain())
+ .add("trust_marks", getTrustMarks())
+ .add("customClaims", getCustomClaims()).toString();
+ }
+
+ /**
+ * Get the array containing the sequence of Entity Statements that compose the Trust Chain.
+ *
+ * @return trust chain
+ */
+ @Nullable public List<String> getTrustChain() {
+ return trustChain;
+ }
+
+ /**
+ * Set the array containing the sequence of Entity Statements that compose the Trust Chain.
+ *
+ * @param chain trust chain
+ */
+ public void setTrustAnchorHints(final @Nullable List<String> chain) {
+ trustChain = chain;
+ }
+
+ /**
+ * Get the array of Trust Marks.
+ *
+ * @return trust marks
+ */
+ @Nullable public List<Map<String, String>> getTrustMarks() {
+ return trustMarks;
+ }
+
+ /**
+ * Set the array of Trust Marks.
+ *
+ * @param marks trust marks
+ */
+ public void setTrustMarks(@Nullable List<Map<String, String>> marks) {
+ trustMarks = marks;
+ }
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
new file mode 100644
index 0000000..3a476f5
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMark.java
@@ -0,0 +1,60 @@
+/*
+ * 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.oidfed.metadata;
+
+import javax.annotation.Nonnull;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.shared.logic.ConstraintViolationException;
+
+/**
+ * A wrapper class extending {@link EntityStatement} with parsed claims related to trust mark.
+ */
+public class TrustMark extends EntityStatement {
+
+ /**
+ * Constructor.
+ *
+ * @param signedJwt entity configuration
+ * @param payload entity configuration payload
+ * @throws ConstraintViolationException if the payload syntax/content is not expected
+ */
+ protected TrustMark(@Nonnull final SignedJWT signedJwt,
+ @Nonnull final TrustMarkPayload payload)
+ throws ConstraintViolationException {
+ super(signedJwt, payload);
+ }
+
+ /**
+ * Parse an {@link TrustMark} from the given JWT by using the given object mapper.
+ *
+ * @param jwt entity statement JWT
+ * @param objectMapper object mapper capable of parsing JWT payload
+ * @return entity configuration
+ * @throws JsonProcessingException if the payload could not be parsed
+ */
+ @Nonnull public static TrustMark parse(@Nonnull final SignedJWT jwt,
+ @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
+ final JavaType objectType = objectMapper.constructType(TrustMarkPayload.class);
+ final TrustMarkPayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
+ assert result != null;
+ return new TrustMark(jwt, result);
+ }
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkPayload.java
new file mode 100644
index 0000000..5413bc7
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkPayload.java
@@ -0,0 +1,126 @@
+/*
+ * 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.oidfed.metadata;
+
+import javax.annotation.Nullable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Trust Mark payload claims as defined by the OpenID Federation 1.0 Section 7.1.
+ */
+public class TrustMarkPayload extends EntityStatementPayload {
+
+ /** An identifier of the type of the Trust Mark. */
+ @JsonProperty("trust_mark_type") private String trustMarkType;
+
+ /** A URL that references a logo for the issued Trust Mark. */
+ @JsonProperty("logo_uri") private String logoUri;
+
+ /** A URL referring to human-readable information about the issuance of the Trust Mark. */
+ @JsonProperty("ref") private String reference;
+
+ /** A Trust Mark delegation JWT. */
+ @JsonProperty("delegation") private String delegation;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("iss", getIssuer())
+ .add("sub", getSubject())
+ .add("iat", getIssuedAt())
+ .add("exp", getExpiration())
+ .add("trust_mark_type", trustMarkType)
+ .add("logo_uri", logoUri)
+ .add("ref", reference)
+ .add("delegation", delegation)
+ .add("customClaims", getCustomClaims()).toString();
+ }
+
+ /**
+ * Get the identifier of the type of the Trust Mark.
+ *
+ * @return trust mark type
+ */
+ @Nullable public String getTrustMarkType() {
+ return trustMarkType;
+ }
+
+ /**
+ * Set the identifier of the type of the Trust Mark.
+ *
+ * @param type trust mark type
+ */
+ public void setTrustMarkType(@Nullable final String type) {
+ trustMarkType = type;
+ }
+
+ /**
+ * Get the URL that references a logo for the issued Trust Mark.
+ *
+ * @return logo URL
+ */
+ @Nullable public String getLogoUri() {
+ return logoUri;
+ }
+
+ /**
+ * Set the URL that references a logo for the issued Trust Mark.
+ *
+ * @param url logo URL
+ */
+ public void setLogoUri(@Nullable final String url) {
+ logoUri = url;
+ }
+
+ /**
+ * Get the URL referring to human-readable information about the issuance of the Trust Mark.
+ *
+ * @return reference URL
+ */
+ @Nullable public String getReference() {
+ return reference;
+ }
+
+ /**
+ * Set the URL referring to human-readable information about the issuance of the Trust Mark.
+ *
+ * @param ref reference URL
+ */
+ public void setReference(@Nullable final String ref) {
+ reference = ref;
+ }
+
+ /**
+ * Get the Trust Mark delegation JWT.
+ *
+ * @return delegation JWT
+ */
+ @Nullable public String getDelegation() {
+ return delegation;
+ }
+
+ /**
+ * Set the Trust Mark delegation JWT.
+ *
+ * @param jwt delegation JWT
+ */
+ public void setDelegation(@Nullable final String jwt) {
+ delegation = jwt;
+ }
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
new file mode 100644
index 0000000..8c566ad
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatus.java
@@ -0,0 +1,60 @@
+/*
+ * 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.oidfed.metadata;
+
+import javax.annotation.Nonnull;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.shared.logic.ConstraintViolationException;
+
+/**
+ * A wrapper class extending {@link EntityStatement} with parsed claims related to trust mark status.
+ */
+public class TrustMarkStatus extends EntityStatement {
+
+ /**
+ * Constructor.
+ *
+ * @param signedJwt entity configuration
+ * @param payload entity configuration payload
+ * @throws ConstraintViolationException if the payload syntax/content is not expected
+ */
+ protected TrustMarkStatus(@Nonnull final SignedJWT signedJwt,
+ @Nonnull final TrustMarkStatusPayload payload)
+ throws ConstraintViolationException {
+ super(signedJwt, payload);
+ }
+
+ /**
+ * Parse an {@link TrustMarkStatus} from the given JWT by using the given object mapper.
+ *
+ * @param jwt entity statement JWT
+ * @param objectMapper object mapper capable of parsing JWT payload
+ * @return entity configuration
+ * @throws JsonProcessingException if the payload could not be parsed
+ */
+ @Nonnull public static TrustMarkStatus parse(@Nonnull final SignedJWT jwt,
+ @Nonnull final ObjectMapper objectMapper) throws JsonProcessingException {
+ final JavaType objectType = objectMapper.constructType(TrustMarkStatusPayload.class);
+ final TrustMarkStatusPayload result = objectMapper.readValue(jwt.getPayload().toString(), objectType);
+ assert result != null;
+ return new TrustMarkStatus(jwt, result);
+ }
+
+}
diff --git a/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusPayload.java b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusPayload.java
new file mode 100644
index 0000000..8dd182d
--- /dev/null
+++ b/idp-oidfed-op-api/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusPayload.java
@@ -0,0 +1,80 @@
+/*
+ * 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.oidfed.metadata;
+
+import javax.annotation.Nullable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Trust Mark Status payload claims as defined by the OpenID Federation 1.0 Section 8.4.2.
+ */
+public class TrustMarkStatusPayload extends EntityStatementPayload {
+
+ /** A Trust Mark. */
+ @JsonProperty("trust_mark") private String trustMark;
+
+ /** A status indicator for the Trust Mark. */
+ @JsonProperty("status") private String status;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("iss", getIssuer())
+ .add("iat", getIssuedAt())
+ .add("trust_mark", trustMark)
+ .add("status", status)
+ .add("customClaims", getCustomClaims()).toString();
+ }
+
+ /**
+ * Get the Trust Mark.
+ *
+ * @return trust mark
+ */
+ @Nullable public String getTrustMark() {
+ return trustMark;
+ }
+
+ /**
+ * Set the Trust Mark.
+ *
+ * @param mark trust mark
+ */
+ public void setTrustMark(@Nullable final String mark) {
+ trustMark = mark;
+ }
+
+ /**
+ * Get the status indicator for the Trust Mark.
+ *
+ * @return status
+ */
+ @Nullable public String getStatus() {
+ return status;
+ }
+
+ /**
+ * Set the status indicator for the Trust Mark.
+ *
+ * @param value status
+ */
+ public void setStatus(@Nullable final String value) {
+ status = value;
+ }
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkResponse.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkResponse.java
deleted file mode 100644
index c132acb..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkResponse.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.oidfed.messaging.impl;
-
-import javax.annotation.Nonnull;
-
-import com.nimbusds.common.contenttype.ContentType;
-import com.nimbusds.jose.JOSEObjectType;
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.http.HTTPResponse;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
-import net.shibboleth.shared.primitive.StringSupport;
-
-/**
- * Response message to the OpenID federation Trust Mark endpoint.
- */
-public class TrustMarkResponse extends AbstractSignedJWTResponse {
-
- /** The JWT type header. */
- @Nonnull
- public static final JOSEObjectType JWT_TYPE_HEADER = new JOSEObjectType("trust-mark+jwt");
-
- /** The content type. */
- @Nonnull public static final ContentType HTTP_RESPONSE_CONTENT_TYPE =
- new ContentType("application", JWT_TYPE_HEADER.toString());
-
- /**
- * Constructor.
- *
- * @param statement JWT
- */
- public TrustMarkResponse(@Nonnull final SignedJWT statement) {
- super(statement);
- }
-
- /** {@inheritDoc} */
- protected ContentType getHttpResponseContentType() {
- return HTTP_RESPONSE_CONTENT_TYPE;
- }
-
- /** {@inheritDoc} */
- protected JOSEObjectType getJWTTypeHeader() {
- return JWT_TYPE_HEADER;
- }
-
- /**
- * Parses a trust mark success response from the given HTTP response.
- *
- * @param httpResponse the HTTP response
- * @return resolve entity success response
- * @throws ParseException if HTTP response could not be parsed into trust mark response
- */
- @Nonnull
- public static TrustMarkResponse parse(@Nonnull final HTTPResponse httpResponse)
- throws ParseException {
-
- httpResponse.ensureStatusCode(HTTPResponse.SC_OK);
- httpResponse.ensureEntityContentType(HTTP_RESPONSE_CONTENT_TYPE);
- final String content = httpResponse.getContent();
-
- if (StringSupport.trimOrNull(content) == null) {
- throw new ParseException("Message body is empty");
- }
-
- try {
- final SignedJWT jwt = SignedJWT.parse(httpResponse.getContent());
- assert jwt != null;
- return new TrustMarkResponse(jwt);
- } catch (final java.text.ParseException | ConstraintViolationException e) {
- throw new ParseException(e.getMessage(), e);
- }
- }
-}
\ No newline at end of file
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkStatusRequest.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkStatusRequest.java
deleted file mode 100644
index 65a50bb..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkStatusRequest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.oidfed.messaging.impl;
-
-import java.net.URI;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.Request;
-import com.nimbusds.oauth2.sdk.http.HTTPRequest;
-
-import net.shibboleth.shared.logic.Constraint;
-
-/**
- * Request message to the OpenID federation Trust Mark Status endpoint.
- */
-public class TrustMarkStatusRequest implements Request {
-
- /** The endpoint URI of the request. */
- @Nonnull private final URI endpointUri;
-
- /** The trust mark JWT for the request. */
- @Nonnull private final SignedJWT trustMark;
-
- /**
- * Constructor.
- *
- * @param uri endpoint URI
- * @param jwt trust mark
- */
- public TrustMarkStatusRequest(@Nonnull final URI uri, @Nonnull final SignedJWT jwt) {
- endpointUri = Constraint.isNotNull(uri, "Endpoint URI cannot be null");
- trustMark = Constraint.isNotNull(jwt, "Trust Mark JWT cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override @Nonnull
- public URI getEndpointURI() {
- return endpointUri;
- }
-
- /** {@inheritDoc} */
- @Override
- public HTTPRequest toHTTPRequest() {
- //TODO
- return null;
- }
-
- /**
- * Get the trust mark for the request.
- *
- * @return trust mark
- */
- @Nullable public SignedJWT getTrustMark() {
- return trustMark;
- }
-
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkStatusResponse.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkStatusResponse.java
deleted file mode 100644
index 9951d1f..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkStatusResponse.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.oidfed.messaging.impl;
-
-import javax.annotation.Nonnull;
-
-import com.nimbusds.common.contenttype.ContentType;
-import com.nimbusds.jose.JOSEObjectType;
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.http.HTTPResponse;
-
-import net.shibboleth.shared.logic.ConstraintViolationException;
-import net.shibboleth.shared.primitive.StringSupport;
-
-/**
- * Response message to the OpenID federation Trust Mark status endpoint.
- */
-public class TrustMarkStatusResponse extends AbstractSignedJWTResponse {
-
- /** The JWT type header. */
- @Nonnull
- public static final JOSEObjectType JWT_TYPE_HEADER = new JOSEObjectType("trust-mark-status-response+jwt");
-
- /** The content type. */
- @Nonnull public static final ContentType HTTP_RESPONSE_CONTENT_TYPE =
- new ContentType("application", JWT_TYPE_HEADER.toString());
-
- /**
- * Constructor.
- *
- * @param statement JWT
- */
- public TrustMarkStatusResponse(@Nonnull final SignedJWT statement) {
- super(statement);
- }
-
- /** {@inheritDoc} */
- protected ContentType getHttpResponseContentType() {
- return HTTP_RESPONSE_CONTENT_TYPE;
- }
-
- /** {@inheritDoc} */
- protected JOSEObjectType getJWTTypeHeader() {
- return JWT_TYPE_HEADER;
- }
-
- /**
- * Parses a trust mark status success response from the given HTTP response.
- *
- * @param httpResponse the HTTP response
- * @return trust mark status success response
- * @throws ParseException if HTTP response could not be parsed into trust mark status response
- */
- @Nonnull
- public static TrustMarkStatusResponse parse(@Nonnull final HTTPResponse httpResponse)
- throws ParseException {
-
- httpResponse.ensureStatusCode(HTTPResponse.SC_OK);
- httpResponse.ensureEntityContentType(HTTP_RESPONSE_CONTENT_TYPE);
- final String content = httpResponse.getContent();
-
- if (StringSupport.trimOrNull(content) == null) {
- throw new ParseException("Message body is empty");
- }
-
- try {
- final SignedJWT jwt = SignedJWT.parse(httpResponse.getContent());
- assert jwt != null;
- return new TrustMarkStatusResponse(jwt);
- } catch (final java.text.ParseException | ConstraintViolationException e) {
- throw new ParseException(e.getMessage(), e);
- }
- }
-}
\ No newline at end of file
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/AbstractFederationEndpointResponseFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/AbstractFederationEndpointResponseFetchingStrategy.java
deleted file mode 100644
index 72f05cf..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/AbstractFederationEndpointResponseFetchingStrategy.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.core5.http.ClassicHttpRequest;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.ProtocolException;
-import org.opensaml.security.httpclient.HttpClientSecurityParameters;
-import org.opensaml.security.httpclient.HttpClientSecuritySupport;
-import org.slf4j.Logger;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.oauth2.sdk.Request;
-
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * An abstract base class for fetching strategies related to OpenID Federation endpoints.
- *
- * @param <R> request message class sent to the federation endpoint
- * @param <C> response message container class stored to the metadata cache
- */
-public abstract class
- AbstractFederationEndpointResponseFetchingStrategy<R extends Request, C extends NimbusResponseContainer>
- extends AbstractIdentifiableInitializableComponent implements Function<CriteriaSet, C> {
-
- /** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(AbstractFederationEndpointResponseFetchingStrategy.class);
-
- /** HTTP client to use. */
- @NonnullAfterInit protected HttpClient httpClient;
-
- /** HTTP client security parameters. */
- @Nullable private HttpClientSecurityParameters httpClientSecurityParameters;
-
- /** JSON object mapper used for decoding JSON into Map. */
- @NonnullAfterInit private ObjectMapper objectMapper;
-
- /** Strategy to fetch request from the criteria set. */
- @NonnullAfterInit private Function<CriteriaSet, R> criteriaToRequestStrategy;
-
- /**
- * Set the {@link HttpClient} to use.
- *
- * @param client HTTP client to use
- */
- public void setHttpClient(@Nonnull final HttpClient client) {
- checkSetterPreconditions();
- httpClient = Constraint.isNotNull(client, "HttpClient cannot be null");
- }
-
- /**
- * Set the optional client security parameters.
- *
- * @param params the new client security parameters
- */
- public void setHttpClientSecurityParameters(@Nullable final HttpClientSecurityParameters params) {
- checkSetterPreconditions();
- httpClientSecurityParameters = params;
- }
-
- /**
- * Set the strategy to fetch request from the criteria set.
- *
- * @param strategy lookup strategy
- */
- public void setCriteriaToRequestStrategy(@Nonnull final Function<CriteriaSet, R> strategy) {
- checkSetterPreconditions();
- criteriaToRequestStrategy = Constraint.isNotNull(strategy, "Criteria to request strategy cannot be null");
- }
-
- /**
-
- * Set the JSON {@link ObjectMapper} used for decoding JSON into Map.
- *
- * @param mapper object mapper
- */
- public void setObjectMapper(@Nonnull final ObjectMapper mapper) {
- checkSetterPreconditions();
-
- objectMapper = Constraint.isNotNull(mapper, "Object mapper cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (httpClient == null) {
- throw new ComponentInitializationException("Httpclient cannot be null");
- }
- if (objectMapper == null) {
- throw new ComponentInitializationException("Object mapper cannot be null");
- }
- if (criteriaToRequestStrategy == null) {
- throw new ComponentInitializationException("Criteria to request strategy cannot be null");
- }
- }
-
- /** {@inheritDoc} */
- @Override @Nullable
- public C apply(@Nullable final CriteriaSet criteria) {
- checkComponentActive();
- if (criteria == null) {
- log.error("No criteria set provided");
- return null;
- }
- final R request = criteriaToRequestStrategy.apply(criteria);
- if (request == null) {
- log.debug("Could not resolve request from criteria {}", criteria);
- return null;
- }
- final ClassicHttpRequest httpRequest = initializeHttpRequest(criteria, request);
- if (httpRequest == null) {
- log.debug("Could not initialize HTTP request from {}", request);
- return null;
- }
- final HttpClientContext httpContext = buildHttpContext(httpRequest);
- try (final ClassicHttpResponse response = httpClient.executeOpen(null, httpRequest, httpContext)) {
- final String scheme = httpRequest.getUri().getScheme();
- assert scheme != null;
- HttpClientSecuritySupport.checkTLSCredentialEvaluated(httpContext, scheme);
- return parseHttpResponse(criteria, request, response);
- } catch (final ProtocolException | URISyntaxException | IOException e) {
- log.debug("Unable to fetch resolve entity response from URI: {}", request.getEndpointURI(), e);
- }
-
- return null;
- }
-
- /**
- * Build the {@link HttpClientContext} instance to be used with {@link #httpClient}.
- *
- * @param request the HTTP client request
- * @return the client context instance
- */
- @Nonnull
- protected HttpClientContext buildHttpContext(@Nonnull final ClassicHttpRequest request) {
- final HttpClientContext clientContext = HttpClientContext.create();
- assert clientContext != null;
- HttpClientSecuritySupport.marshalSecurityParameters(clientContext, httpClientSecurityParameters, false);
- HttpClientSecuritySupport.addDefaultTLSTrustEngineCriteria(clientContext, request);
- return clientContext;
- }
-
- /**
- * Initializes the {@link ClassicHttpRequest} to be used with {@link #httpClient}.
- *
- * @param criteria criteria set
- * @param request Nimbus request message
- * @return the request to be used with {@link #httpClient}
- */
- @Nullable protected abstract ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
- @Nonnull R request);
-
- /**
- * Parses the response message container to be stored in the metadata cache.
- *
- * @param criteria criteria set
- * @param request Nimbus request message
- * @param response the HTTP response obtained from {@link #httpClient}
- * @return the response message container
- * @throws ProtocolException if HTTP protocol violation occurs
- * @throws IOException if generic I/O exception occurs
- */
- @Nullable protected abstract C parseHttpResponse(@Nonnull final CriteriaSet criteria, @Nonnull final R request,
- @Nullable final ClassicHttpResponse response) throws ProtocolException, IOException;
-
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseSignatureValidationFilterStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseSignatureValidationFilterStrategy.java
deleted file mode 100644
index c7b1d33..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityResponseSignatureValidationFilterStrategy.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.text.ParseException;
-import java.util.List;
-import java.util.function.BiFunction;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.security.trust.TrustEngine;
-import org.slf4j.Logger;
-
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityResponse;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteEntityConfigurationContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityStatementCriterion;
-import net.shibboleth.oidc.metadata.cache.MetadataCache;
-import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
-import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * Default signature validating filter for resolve entity response. The signature validation is performed via
- * configurable {@link TrustEngine}.
- */
- at ThreadSafeAfterInit
-public class DefaultResolveEntityResponseSignatureValidationFilterStrategy
- extends AbstractTrustEngineSignatureValidationComponent
- implements BiFunction<ResolveEntityResponseContainer, MetadataFilterContext, ResolveEntityResponseContainer> {
-
- /** Class logger. */
- @Nonnull private Logger log =
- LoggerFactory.getLogger(DefaultResolveEntityResponseSignatureValidationFilterStrategy.class);
-
- /** Cache used to fetch the issuer entity configuration from. */
- @NonnullAfterInit private MetadataCache<RemoteEntityConfigurationContainer> entityConfigurationCache;
-
- /**
- * Set the cache used to fetch the issuer entity configuration from.
- *
- * @param cache cache used to fetch the issuer entity configuration from
- */
- public void setEntityConfigurationCache(@Nonnull final MetadataCache<RemoteEntityConfigurationContainer> cache) {
- checkSetterPreconditions();
- entityConfigurationCache = Constraint.isNotNull(cache, "Entity Configuration cache cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (entityConfigurationCache == null) {
- throw new ComponentInitializationException("Entity Configuration cache cannot be null");
- }
- }
-
- /** {@inheritDoc} */
- @Override @Nullable
- public ResolveEntityResponseContainer apply(@Nullable final ResolveEntityResponseContainer response,
- @Nullable final MetadataFilterContext filterContext) {
- checkComponentActive();
- if (response == null) {
- return null;
- }
- if (response.getResponse() instanceof ResolveEntityResponse successResponse) {
- final SignedJWT jwt = successResponse.getJWT();
- final String entityId;
- try {
- entityId = jwt.getJWTClaimsSet().getIssuer();
- } catch (final ParseException e) {
- log.error("Could not parse issuer entity ID value from the response", e);
- return null;
- }
- final EntityStatement issuerStatement = fetchIssuerStatement(entityId);
- if (issuerStatement == null) {
- return null;
- }
- log.trace("Starting signature validation of success response from {}", entityId);
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityStatementCriterion(issuerStatement));
- if (validateJwt(jwt, criteria, entityId)) {
- return response;
- }
- } else {
- log.trace("Ignoring signagure validation for the error response");
- return response;
- }
- return null;
- }
-
- /**
- * Fetch the issuer entity configuration from the metadata cache.
- *
- * @param issuer the issuer entity ID
- * @return the issuer entity configuration, or null if could not be fetched
- */
- @Nullable protected EntityStatement fetchIssuerStatement(@Nonnull final String issuer) {
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
- try {
- final List<RemoteEntityConfigurationContainer> result = entityConfigurationCache.get(criteria);
- if (!result.isEmpty()) {
- return result.get(0).getEntityStatement();
- }
- } catch (final MetadataCacheException e) {
- log.debug("Error while fetching issuer entity configuration for {}", issuer, e);
- }
- log.warn("Could not fetch entity configuration for {}", issuer);
- return null;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityTrustChainFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityTrustChainFetchingStrategy.java
deleted file mode 100644
index b3c2d3b..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultResolveEntityTrustChainFetchingStrategy.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.core5.http.ClassicHttpRequest;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.ContentType;
-import org.apache.hc.core5.http.HttpHeaders;
-import org.apache.hc.core5.http.NameValuePair;
-import org.apache.hc.core5.http.ProtocolException;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.apache.hc.core5.http.message.BasicNameValuePair;
-import org.apache.hc.core5.net.URIBuilder;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.http.HTTPResponse;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityResponse;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * Default strategy for fetching trust chain data via resolve entity API for a request specified in the criteria set.
- */
- at ThreadSafeAfterInit
-public class DefaultResolveEntityTrustChainFetchingStrategy
- extends AbstractFederationEndpointResponseFetchingStrategy<ResolveEntityRequest, ResolveEntityResponseContainer> {
-
- /** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(DefaultResolveEntityTrustChainFetchingStrategy.class);
-
- /**
- * Constructor.
- */
- public DefaultResolveEntityTrustChainFetchingStrategy() {
- setCriteriaToRequestStrategy(criteria -> {
- final ResolveEntityRequestCriterion requestCriterion = criteria.get(ResolveEntityRequestCriterion.class);
- if (requestCriterion == null) {
- log.debug("No request criterion given, returning null");
- return null;
- }
- return requestCriterion.getRequest();
- });
- }
-
- /** {@inheritDoc} */
- @Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
- @Nonnull ResolveEntityRequest resolveRequest) {
- final HttpGet httpRequest = new HttpGet(resolveRequest.getEndpointURI());
- final List<NameValuePair> nvps = new ArrayList<>();
- nvps.add(new BasicNameValuePair("sub", resolveRequest.getSubject()));
- resolveRequest.getTrustAnchors()
- .forEach(trustAnchor -> nvps.add(new BasicNameValuePair("trust_anchor", trustAnchor)));
- resolveRequest.getEntityTypes()
- .forEach(entityType -> nvps.add(new BasicNameValuePair("entity_type", entityType)));
- final URI uri;
- try {
- uri = new URIBuilder(httpRequest.getUri()).addParameters(nvps).build();
- } catch (final URISyntaxException e) {
- log.error("Could not build endpoint URI for the resolve entity request", e);
- return null;
- }
- log.debug("Using URI {} for fetching resolve entity API response", uri);
- httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
- httpRequest.setUri(uri);
- return httpRequest;
- }
-
- /** {@inheritDoc} */
- @Nullable protected ResolveEntityResponseContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
- @Nonnull final ResolveEntityRequest request, @Nullable final ClassicHttpResponse response)
- throws ProtocolException, IOException {
- final ResponseContainerExpirationCriterion expirationCriterion =
- criteria.get(ResponseContainerExpirationCriterion.class);
- if (expirationCriterion == null) {
- log.debug("No expiration criterion given, returning null");
- return null;
- }
- if (response != null) {
- final HTTPResponse nimbusResponse = new HTTPResponse(response.getCode());
- nimbusResponse.setContent(EntityUtils.toString(response.getEntity()));
- try {
- nimbusResponse.setContentType(response.getEntity().getContentType());
- final ResolveEntityResponse resolveResponse = ResolveEntityResponse.parse(nimbusResponse);
- final Instant expirationTime = expirationCriterion.getExpirationInstant();
- return new ResolveEntityResponseContainer(resolveResponse, request, expirationTime);
- } catch (final ParseException e) {
- log.warn("Could not parse resolve entity response from URI: {}", request.getEndpointURI(), e);
- }
- } else {
- log.debug("Unable to fetch resolve entity response from URI: {} (null response)", request.getEndpointURI());
- }
-
- return null;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkFetchingStrategy.java
deleted file mode 100644
index 890d024..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkFetchingStrategy.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.core5.http.ClassicHttpRequest;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.NameValuePair;
-import org.apache.hc.core5.http.ProtocolException;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.apache.hc.core5.http.message.BasicNameValuePair;
-import org.apache.hc.core5.net.URIBuilder;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.http.HTTPResponse;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkResponse;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * Default strategy for fetching trust mark via Trust Mark API for the request specified in the criteria set. The
- * response is stored inside a {@link TrustMarkResponseContainer}.
- */
- at ThreadSafeAfterInit
-public class DefaultTrustMarkFetchingStrategy
- extends AbstractFederationEndpointResponseFetchingStrategy<TrustMarkRequest, TrustMarkResponseContainer> {
-
- /** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(DefaultTrustMarkFetchingStrategy.class);
-
- /**
- * Constructor.
- */
- public DefaultTrustMarkFetchingStrategy() {
- setCriteriaToRequestStrategy(criteria -> {
- final TrustMarkRequestCriterion requestCriterion = criteria.get(TrustMarkRequestCriterion.class);
- if (requestCriterion == null) {
- log.debug("No request criterion given, returning null");
- return null;
- }
- return requestCriterion.getRequest();
- });
- }
-
- /** {@inheritDoc} */
- @Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
- @Nonnull TrustMarkRequest request) {
- final HttpGet httpRequest = new HttpGet(request.getEndpointURI());
- final List<NameValuePair> nvps = new ArrayList<>();
- nvps.add(new BasicNameValuePair("trust_mark_type", request.getTrustMarkType()));
- nvps.add(new BasicNameValuePair("sub", request.getSubject()));
- try {
- final URI uri = new URIBuilder(httpRequest.getUri()).addParameters(nvps).build();
- httpRequest.setUri(uri);
- } catch (final URISyntaxException e) {
- log.error("Could not create URI with the given parameters {}", request, e);
- }
- return httpRequest;
- }
-
- /** {@inheritDoc} */
- @Nullable protected TrustMarkResponseContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
- @Nonnull final TrustMarkRequest request, @Nullable final ClassicHttpResponse response)
- throws ProtocolException, IOException {
- final ResponseContainerExpirationCriterion expirationCriterion =
- criteria.get(ResponseContainerExpirationCriterion.class);
- if (expirationCriterion == null) {
- log.debug("No expiration criterion given, returning null");
- return null;
- }
- if (response != null) {
- final HTTPResponse nimbusResponse = new HTTPResponse(response.getCode());
- nimbusResponse.setContent(EntityUtils.toString(response.getEntity()));
- try {
- nimbusResponse.setContentType(response.getEntity().getContentType());
- final TrustMarkResponse parsedResponse = TrustMarkResponse.parse(nimbusResponse);
- final Instant expirationTime = expirationCriterion.getExpirationInstant();
- return new TrustMarkResponseContainer(parsedResponse, request, parsedResponse.getJWT(), expirationTime);
- } catch (final ParseException e) {
- log.warn("Could not parse resolve entity response from URI: {}", request.getEndpointURI(), e);
- }
- } else {
- log.debug("Unable to fetch resolve entity response from URI: {} (null response)", request.getEndpointURI());
- }
-
- return null;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkResponseSignatureValidationFilterStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkResponseSignatureValidationFilterStrategy.java
deleted file mode 100644
index 3520d8b..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkResponseSignatureValidationFilterStrategy.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.text.ParseException;
-import java.util.List;
-import java.util.function.BiFunction;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.security.trust.TrustEngine;
-import org.slf4j.Logger;
-
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkResponse;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteTrustChainsContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityStatementCriterion;
-import net.shibboleth.oidc.metadata.cache.MetadataCache;
-import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
-import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * Default signature validating filter for Trust Mark response. The signature validation is performed via
- * configurable {@link TrustEngine}.
- */
- at ThreadSafeAfterInit
-public class DefaultTrustMarkResponseSignatureValidationFilterStrategy
- extends AbstractTrustEngineSignatureValidationComponent
- implements BiFunction<TrustMarkResponseContainer, MetadataFilterContext, TrustMarkResponseContainer> {
-
- /** Class logger. */
- @Nonnull private Logger log =
- LoggerFactory.getLogger(DefaultTrustMarkResponseSignatureValidationFilterStrategy.class);
-
- /** Cache used to fetch the issuer entity configuration from. */
- @NonnullAfterInit private MetadataCache<RemoteTrustChainsContainer> trustChainCache;
-
- /**
- * Set the cache used to fetch the trust chain for the trust mark issuer from.
- *
- * @param cache cache used to fetch the trust chain for the trust mark issuer from
- */
- public void setTrustChainCache(@Nonnull final MetadataCache<RemoteTrustChainsContainer> cache) {
- checkSetterPreconditions();
- trustChainCache = Constraint.isNotNull(cache, "Trust Chain cache cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (trustChainCache == null) {
- throw new ComponentInitializationException("Trust Chain cache cannot be null");
- }
- }
-
- /** {@inheritDoc} */
- @Override @Nullable
- public TrustMarkResponseContainer apply(@Nullable final TrustMarkResponseContainer response,
- @Nullable final MetadataFilterContext filterContext) {
- checkComponentActive();
- if (response == null) {
- return null;
- }
- if (response.getResponse() instanceof TrustMarkResponse successResponse) {
- final SignedJWT jwt = successResponse.getJWT();
- final String entityId;
- try {
- entityId = jwt.getJWTClaimsSet().getIssuer();
- } catch (final ParseException e) {
- log.error("Could not parse issuer entity ID value from the response", e);
- return null;
- }
- final EntityStatement issuerStatement = fetchIssuerStatement(entityId);
- if (issuerStatement == null) {
- return null;
- }
- log.trace("Starting signature validation of success response from {}", entityId);
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityStatementCriterion(issuerStatement));
- if (validateJwt(jwt, criteria, entityId)) {
- return response;
- }
- } else {
- log.trace("Ignoring signature validation for the error response");
- return response;
- }
- return null;
- }
-
- /**
- * Fetch the issuer entity configuration from the trust chain metadata cache.
- *
- * @param issuer the issuer entity ID
- * @return the issuer entity configuration, or null if could not be fetched
- */
- @Nullable protected EntityStatement fetchIssuerStatement(@Nonnull final String issuer) {
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
- try {
- final List<RemoteTrustChainsContainer> result = trustChainCache.get(criteria);
- if (!result.isEmpty() && !result.get(0).getTrustChains().isEmpty()) {
- return result.get(0).getTrustChains().get(0).get(0);
- }
- } catch (final MetadataCacheException e) {
- log.debug("Error while fetching issuer trust chain for {}", issuer, e);
- }
- log.warn("Could not fetch entity configuration for {}", issuer);
- return null;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkStatusFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkStatusFetchingStrategy.java
deleted file mode 100644
index 55184cc..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkStatusFetchingStrategy.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.methods.HttpPost;
-import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
-import org.apache.hc.core5.http.ClassicHttpRequest;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.ContentType;
-import org.apache.hc.core5.http.HttpHeaders;
-import org.apache.hc.core5.http.NameValuePair;
-import org.apache.hc.core5.http.ProtocolException;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.apache.hc.core5.http.message.BasicNameValuePair;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.http.HTTPResponse;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkStatusRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkStatusResponse;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * Default strategy for fetching trust mark status via Trust Mark STatus API for the request specified in the criteria
- * set. The status response is stored inside a {@link TrustMarkStatusResponseContainer}.
- */
- at ThreadSafeAfterInit
-public class DefaultTrustMarkStatusFetchingStrategy
- extends AbstractFederationEndpointResponseFetchingStrategy<TrustMarkStatusRequest, TrustMarkStatusResponseContainer> {
-
- /** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(DefaultTrustMarkStatusFetchingStrategy.class);
-
- /**
- * Constructor.
- */
- public DefaultTrustMarkStatusFetchingStrategy() {
- setCriteriaToRequestStrategy(criteria -> {
- final TrustMarkStatusRequestCriterion requestCriterion =
- criteria.get(TrustMarkStatusRequestCriterion.class);
- if (requestCriterion == null) {
- log.debug("No request criterion given, returning null");
- return null;
- }
- return requestCriterion.getRequest();
- });
- }
-
- /** {@inheritDoc} */
- @Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
- @Nonnull TrustMarkStatusRequest request) {
- final HttpPost httpRequest = new HttpPost(request.getEndpointURI());
- final List<NameValuePair> nvps = new ArrayList<>();
- nvps.add(new BasicNameValuePair("trust_mark", request.getTrustMark().serialize()));
- final UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
- httpRequest.setEntity(urlEncodedFormEntity);
- httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
-
- return httpRequest;
- }
-
- /** {@inheritDoc} */
- @Nullable protected TrustMarkStatusResponseContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
- @Nonnull final TrustMarkStatusRequest request, @Nullable final ClassicHttpResponse response)
- throws ProtocolException, IOException {
- final ResponseContainerExpirationCriterion expirationCriterion =
- criteria.get(ResponseContainerExpirationCriterion.class);
- if (expirationCriterion == null) {
- log.debug("No expiration criterion given, returning null");
- return null;
- }
- if (response != null) {
- final HTTPResponse nimbusResponse = new HTTPResponse(response.getCode());
- nimbusResponse.setContent(EntityUtils.toString(response.getEntity()));
- try {
- nimbusResponse.setContentType(response.getEntity().getContentType());
- final TrustMarkStatusResponse statusResponse = TrustMarkStatusResponse.parse(nimbusResponse);
- final Instant expirationTime = expirationCriterion.getExpirationInstant();
- return new TrustMarkStatusResponseContainer(statusResponse, request.getTrustMark(), expirationTime);
- } catch (final ParseException e) {
- log.warn("Could not parse resolve entity response from URI: {}", request.getEndpointURI(), e);
- }
- } else {
- log.debug("Unable to fetch resolve entity response from URI: {} (null response)", request.getEndpointURI());
- }
-
- return null;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java
index 46d2aa4..7caa686 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java
@@ -15,7 +15,6 @@
package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
import java.net.URI;
-import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -166,15 +165,12 @@ public class EntityStatementHelper {
* @param cache metadata cache used for fetching the entity configuration
* @param entityId entity ID of the entity
* @param endpointId the endpoint ID
- * @param expiration expiration passed to the entity configuration cache
* @return endpoint URI
*/
@Nullable public static URI fetchEndpointUriFromFederationEntity(
@Nonnull MetadataCache<RemoteEntityConfigurationContainer> cache,
- @Nonnull final String entityId, @Nonnull final String endpointId,
- @Nonnull final Instant expiration) {
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(entityId),
- new ResponseContainerExpirationCriterion(expiration));
+ @Nonnull final String entityId, @Nonnull final String endpointId) {
+ final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(entityId));
try {
final List<RemoteEntityConfigurationContainer> result = cache.get(criteria);
if (!result.isEmpty()) {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkResponseContainer.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkResponseContainer.java
deleted file mode 100644
index 755b8fc..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkResponseContainer.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.io.Serializable;
-import java.time.Instant;
-
-import javax.annotation.Nonnull;
-
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.Response;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkRequest;
-import net.shibboleth.shared.logic.Constraint;
-
-/**
- * A container class for metadata caches carrying request and response message details related to Trust Mark API.
- */
-public class TrustMarkResponseContainer extends NimbusResponseContainer implements Serializable {
-
- /** Serial version UID. */
- private static final long serialVersionUID = 756269383556865370L;
-
- /** Request message used for obtaining the Trust Mark. */
- @Nonnull private final TrustMarkRequest request;
-
- /** Trust Mark. */
- @Nonnull private final SignedJWT trustMark;
-
- /**
- * Constructor.
- *
- * @param responseMessage response message
- * @param requestMessage request message
- * @param jwt trust mark
- * @param expirationInstant expiration instant
- */
- public TrustMarkResponseContainer(@Nonnull final Response responseMessage,
- @Nonnull final TrustMarkRequest requestMessage, @Nonnull final SignedJWT jwt,
- @Nonnull final Instant expirationInstant) {
- super(responseMessage, expirationInstant);
- request = Constraint.isNotNull(requestMessage, "Request nessage cannot be null");
- trustMark = Constraint.isNotNull(jwt, "Trust Mark JWT cannot be null");
- }
-
- /**
- * Get request message.
- *
- * @return request message
- */
- public TrustMarkRequest getRequestMessage() {
- return request;
- }
-
- /**
- * Get trust mark.
- *
- * @return trust mark
- */
- public SignedJWT getTrustMark() {
- return trustMark;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusResponseContainer.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusResponseContainer.java
deleted file mode 100644
index 3a2652a..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusResponseContainer.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.oidfed.metadata;
-
-import java.io.Serializable;
-import java.time.Instant;
-
-import javax.annotation.Nonnull;
-
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.Response;
-
-import net.shibboleth.shared.logic.Constraint;
-
-/**
- * A container class for metadata caches carrying request and response message details related to Trust Mark Status API.
- */
-public class TrustMarkStatusResponseContainer extends NimbusResponseContainer implements Serializable {
-
- /** Serial version UID. */
- private static final long serialVersionUID = 756269383556865370L;
-
- /** Trust Mark. */
- @Nonnull private final SignedJWT trustMark;
-
- /**
- * Constructor.
- *
- * @param responseMessage response message
- * @param jwt trust mark
- * @param expirationInstant expiration instant
- */
- public TrustMarkStatusResponseContainer(@Nonnull final Response responseMessage,
- @Nonnull final SignedJWT jwt, @Nonnull final Instant expirationInstant) {
- super(responseMessage, expirationInstant);
- trustMark = Constraint.isNotNull(jwt, "Trust Mark JWT cannot be null");
- }
-
- /**
- * Get request message.
- *
- * @return request message
- */
- public SignedJWT getTrustMark() {
- return trustMark;
- }
-
- /**
- * Get response message.
- *
- * @return response message
- */
- @Nonnull public Response getResponse() {
- return super.getResponse();
- }
-
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ec/DefaultEntityConfigurationContentValidationCondition.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultEntityStatementContentValidationCondition.java
similarity index 83%
rename from idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ec/DefaultEntityConfigurationContentValidationCondition.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultEntityStatementContentValidationCondition.java
index 21f03d5..f357f51 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ec/DefaultEntityConfigurationContentValidationCondition.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultEntityStatementContentValidationCondition.java
@@ -12,7 +12,7 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ec;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache;
import java.text.ParseException;
import java.util.function.BiPredicate;
@@ -23,9 +23,9 @@ import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
+import com.nimbusds.jwt.JWTClaimsSet;
+
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.BaseExpirableEntityStatementContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteEntityConfigurationContainer;
import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
import net.shibboleth.oidc.jwt.claims.JWTValidationException;
import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
@@ -36,19 +36,19 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
/**
- * Default content validating filter for entity configuration. Verifies that the
- * {@link RemoteEntityConfigurationContainer#getEntityId()} matches with the subject of the entity configuration and
- * validates the claims via configurable claims validator. Note that the {@link ProfileRequestContext} is not fed to
+ * Default content validating filter for entity statement. Verifies that the
+ * {@link RemoteEntityConfigurationContainer#getEntityId()} matches with the subject of the entity statement and
+ * validates the claims via configurable claims validator. Note that an empty {@link ProfileRequestContext} is fed to
* the claims validator.
*/
@ThreadSafeAfterInit
-public class DefaultEntityConfigurationContentValidationCondition
+public class DefaultEntityStatementContentValidationCondition
extends AbstractIdentifiableInitializableComponent
implements BiPredicate<BaseExpirableEntityStatementContainer, MetadataFilterContext> {
/** Class logger. */
@Nonnull private Logger log =
- LoggerFactory.getLogger(DefaultEntityConfigurationContentValidationCondition.class);
+ LoggerFactory.getLogger(DefaultEntityStatementContentValidationCondition.class);
/** The claims validator to use for validating the entity statement claims. */
@NonnullAfterInit private ClaimsValidator claimsValidator;
@@ -74,6 +74,7 @@ public class DefaultEntityConfigurationContentValidationCondition
}
final EntityStatement statement = responseContainer.getEntityStatement();
+ assert statement != null;
if (!responseContainer.getEntityId().equals(statement.getParsedPayload().getSubject())) {
log.warn("Entity statement subject {} does not match with the requested entity ID {}",
statement.getParsedPayload().getSubject(), responseContainer.getEntityId());
@@ -81,7 +82,9 @@ public class DefaultEntityConfigurationContentValidationCondition
}
try {
- claimsValidator.validate(statement.getJwt().getJWTClaimsSet(), null);
+ final JWTClaimsSet claimsSet = statement.getJwt().getJWTClaimsSet();
+ assert claimsSet != null;
+ claimsValidator.validate(claimsSet, new ProfileRequestContext());
} catch (final JWTValidationException | ParseException e) {
log.warn("Claims validation failed for entity statement {}", responseContainer.getEntityId(), e);
return false;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultEntityStatementValidationCriteriaSetLookupFunction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultEntityStatementValidationCriteriaSetLookupFunction.java
new file mode 100644
index 0000000..d4075d5
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultEntityStatementValidationCriteriaSetLookupFunction.java
@@ -0,0 +1,113 @@
+/*
+ * 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.oidfed.metadata.cache;
+
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubjectEntityIDCriterion;
+import net.shibboleth.oidc.metadata.cache.MetadataCache;
+import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
+
+/**
+ * Default criteria set lookup strategy for {@link BaseExpirableEntityStatementContainer}.
+ */
+ at ThreadSafeAfterInit
+public class DefaultEntityStatementValidationCriteriaSetLookupFunction
+ extends AbstractIdentifiableInitializableComponent
+ implements Function<BaseExpirableEntityStatementContainer, CriteriaSet> {
+
+ /** Class logger. */
+ @Nonnull
+ private Logger log = LoggerFactory.getLogger(DefaultEntityStatementValidationCriteriaSetLookupFunction.class);
+
+ /** Metadata cache used for fetching issuer entity configuration. */
+ @NonnullAfterInit private MetadataCache<RemoteEntityConfigurationContainer> entityConfigurationCache;
+
+ /**
+ * Set the metadata cache used for fetching issuer entity configuration.
+ *
+ * @param cache entity configuration cache
+ */
+ public void setEntityConfigurationCache(@Nonnull final MetadataCache<RemoteEntityConfigurationContainer> cache) {
+ checkSetterPreconditions();
+ entityConfigurationCache = Constraint.isNotNull(cache, "Entity configuration cache cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+ if (entityConfigurationCache == null) {
+ throw new ComponentInitializationException("Trust Engine cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nullable
+ public CriteriaSet apply(@Nullable final BaseExpirableEntityStatementContainer metadataContainer) {
+ if (metadataContainer == null || metadataContainer.getEntityStatement() == null) {
+ log.debug("Entity statement is not found from the container, returning null");
+ return null;
+ }
+ final EntityStatement statement = metadataContainer.getEntityStatement();
+ assert statement != null;
+ final SubjectEntityStatementCriterion subjectCriterion = new SubjectEntityStatementCriterion(statement);
+ final IssuerEntityStatementCriterion issuerCriterion = getIssuerCriterion(statement);
+ if (issuerCriterion == null) {
+ log.debug("Issuer statement could not be fetched, returning null");
+ return null;
+ }
+ return new CriteriaSet(subjectCriterion, issuerCriterion);
+ }
+
+ /**
+ * Fetch the issuer entity configuration from the metadata cache and initialize the criterion.
+ *
+ * @param statement the entity statement whose issuer is fetched
+ * @return the issuer entity configuration, or null if could not be fetched
+ */
+ @Nullable protected IssuerEntityStatementCriterion getIssuerCriterion(
+ @Nonnull final EntityStatement statement) {
+ final String issuer = statement.getIssuer();
+ final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
+ try {
+ final List<RemoteEntityConfigurationContainer> result = entityConfigurationCache.get(criteria);
+ if (!result.isEmpty()) {
+ final EntityStatement issuerStatement = result.get(0).getEntityStatement();
+ if (issuerStatement != null) {
+ return new IssuerEntityStatementCriterion(issuerStatement);
+ }
+ }
+ } catch (final MetadataCacheException e) {
+ log.debug("Error while fetching issuer entity configuration for {}", issuer, e);
+ }
+ log.warn("Could not fetch entity configuration for {}", issuer);
+ return null;
+ }
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/DefaultResolveEntityTrustChainFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/DefaultResolveEntityTrustChainFetchingStrategy.java
new file mode 100644
index 0000000..29fcc1e
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/DefaultResolveEntityTrustChainFetchingStrategy.java
@@ -0,0 +1,134 @@
+/*
+ * 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.oidfed.metadata.cache.remoteresolver;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
+import org.apache.hc.core5.net.URIBuilder;
+import org.slf4j.Logger;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.AbstractFederationEndpointResponseFetchingStrategy;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
+
+/**
+ * Default strategy for fetching trust chain data via resolve entity API for a request specified in the criteria set.
+ */
+ at ThreadSafeAfterInit
+public class DefaultResolveEntityTrustChainFetchingStrategy
+ extends AbstractFederationEndpointResponseFetchingStrategy
+ <RemoteResolveEntityCacheContainerIdentifier, RemoteResolveEntityResponseContainer> {
+
+ /** The JWT type header. */
+ @Nonnull
+ public static final JOSEObjectType JWT_TYPE_HEADER = new JOSEObjectType("resolve-response+jwt");
+
+ /** The HTTP response content type. */
+ @Nonnull public static final String HTTP_RESPONSE_CONTENT_TYPE = "application/" + JWT_TYPE_HEADER.toString();
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(DefaultResolveEntityTrustChainFetchingStrategy.class);
+
+ /**
+ * Constructor.
+ */
+ public DefaultResolveEntityTrustChainFetchingStrategy() {
+ setCriteriaToRequestDataStrategy(criteria -> {
+ final RemoteResolveEntityCacheIdentifierCriterion identifierCriterion =
+ criteria.get(RemoteResolveEntityCacheIdentifierCriterion.class);
+ if (identifierCriterion == null) {
+ log.debug("No identifier criterion given, returning null");
+ return null;
+ }
+ return identifierCriterion.getIdentifier();
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
+ @Nonnull RemoteResolveEntityCacheContainerIdentifier identifier) {
+ final HttpGet httpRequest = new HttpGet(identifier.getEndpoint());
+ final List<NameValuePair> nvps = new ArrayList<>();
+ nvps.add(new BasicNameValuePair("sub", identifier.getSubject()));
+ identifier.getTrustAnchors().forEach(anchor -> nvps.add(new BasicNameValuePair("trust_anchor", anchor)));
+ identifier.getEntityTypes().forEach(type -> nvps.add(new BasicNameValuePair("entity_type", type)));
+ try {
+ final URI uri = new URIBuilder(httpRequest.getUri()).addParameters(nvps).build();
+ httpRequest.setUri(uri);
+ } catch (final URISyntaxException e) {
+ log.error("Could not create URI with the given parameters {}", identifier, e);
+ }
+ return httpRequest;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable protected RemoteResolveEntityResponseContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
+ @Nonnull final RemoteResolveEntityCacheContainerIdentifier identifier,
+ @Nullable final ClassicHttpResponse response, @Nonnull final Instant validExpiration,
+ @Nonnull final Instant invalidExpiration)
+ throws ProtocolException, IOException {
+ if (response != null) {
+ if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
+ log.warn("Unexpected content type: {}", response.getEntity().getContentType());
+ return new RemoteResolveEntityResponseContainer(identifier, null, validExpiration, invalidExpiration);
+ }
+
+ try {
+ final SignedJWT jwt = SignedJWT.parse(EntityUtils.toString(response.getEntity()));
+ if (!JWT_TYPE_HEADER.equals(jwt.getHeader().getType())) {
+ log.warn("Unexpected JWT type header {}", jwt.getHeader().getType());
+ return new RemoteResolveEntityResponseContainer(identifier, null, validExpiration,
+ invalidExpiration);
+ }
+ assert objectMapper != null;
+ final ResolveEntityResponse resolveEntity = ResolveEntityResponse.parse(jwt, objectMapper);
+ return new RemoteResolveEntityResponseContainer(
+ identifier, resolveEntity, validExpiration, invalidExpiration);
+ } catch (final JsonProcessingException e) {
+ log.warn("Could not deserialize entity statement payload from the response", e);
+ } catch (final ConstraintViolationException e) {
+ log.warn("Parsed entity configuration claims did not pass syntax validation", e);
+ } catch (java.text.ParseException e) {
+ log.warn("Could not parse JWT from the response", e);
+ }
+ } else {
+ log.debug("Unable to fetch resolve entity response: {} (null response)", identifier.getEndpoint());
+ }
+
+ return new RemoteResolveEntityResponseContainer(identifier, null, validExpiration, invalidExpiration);
+ }
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityCacheContainerIdentifier.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityCacheContainerIdentifier.java
new file mode 100644
index 0000000..9e00ca9
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityCacheContainerIdentifier.java
@@ -0,0 +1,143 @@
+/*
+ * 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.oidfed.metadata.cache.remoteresolver;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.base.MoreObjects;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * Default identifier for trust mark within {@link RemoteResolveEntityResponseContainer}.
+ */
+public class RemoteResolveEntityCacheContainerIdentifier implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -4143516153785776493L;
+
+ /** The endpoint URI of the request. */
+ @Nonnull @NotEmpty private final String endpoint;
+
+ /** The requested subject. */
+ @Nonnull @NotEmpty private final String subject;
+
+ /** The requested trust anchors. */
+ @Nonnull @NotEmpty private final List<String> trustAnchors;
+
+ /** The requested entity types to resolve. */
+ @Nonnull private final List<String> entityTypes;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param uri endpoint URI
+ * @param sub subject
+ * @param anchors trust anchors
+ * @param types optional entity types
+ */
+ public RemoteResolveEntityCacheContainerIdentifier(@Nonnull final String uri,
+ @Nonnull @NotEmpty final String sub,
+ @Nonnull @NotEmpty final List<String> anchors,
+ @Nullable final List<String> types) {
+ endpoint = Constraint.isNotEmpty(uri, "Endpoint URI cannot be null");
+ subject = Constraint.isNotNull(sub, "Subject cannot be empty");
+ Constraint.isNotEmpty(anchors, "Trust anchors cannot be empty");
+ trustAnchors = anchors;
+ entityTypes = types == null ? CollectionSupport.emptyList() : CollectionSupport.copyToList(types);
+ }
+
+ /**
+ * Returns the requested subject.
+ *
+ * @return The subject.
+ */
+ @Nonnull @NotEmpty public String getSubject() {
+ return subject;
+ }
+
+ /**
+ * Returns the requested trust anchor.
+ *
+ * @return The trust anchor.
+ */
+ @Nonnull @NotEmpty public List<String> getTrustAnchors() {
+ return trustAnchors;
+ }
+
+ /**
+ * Returns the requested entity type to resolve.
+ *
+ * @return The entity type to resolve.
+ */
+ @Nonnull public List<String> getEntityTypes() {
+ return entityTypes;
+ }
+
+ /**
+ * Get the endpoint for the request.
+ *
+ * @return endpoint
+ */
+ @Nonnull @NotEmpty public String getEndpoint() {
+ return endpoint;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("subject", getSubject())
+ .add("trustAnchors", getTrustAnchors())
+ .add("entityTypes", getEntityTypes())
+ .add("endpoint", getEndpoint())
+ .toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return Objects.hash(endpoint, subject, trustAnchors, entityTypes);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final RemoteResolveEntityCacheContainerIdentifier other = (RemoteResolveEntityCacheContainerIdentifier) obj;
+ return endpoint.equals(other.endpoint) && subject.equals(other.subject)
+ && trustAnchors.containsAll(other.trustAnchors) && other.trustAnchors.containsAll(trustAnchors)
+ && entityTypes.containsAll(other.entityTypes) && other.entityTypes.containsAll(entityTypes);
+
+ }
+
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusRequestCriterion.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityCacheIdentifierCriterion.java
similarity index 53%
copy from idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusRequestCriterion.java
copy to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityCacheIdentifierCriterion.java
index f33a060..04da259 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusRequestCriterion.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityCacheIdentifierCriterion.java
@@ -12,52 +12,51 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remoteresolver;
import java.util.Objects;
import javax.annotation.Nonnull;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkStatusRequest;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.resolver.Criterion;
/**
- * A {@link Criterion} representing request message to a Trust Mark Status API.
+ * A {@link Criterion} representing request message details to Resolve Entity API.
*/
-public class TrustMarkStatusRequestCriterion implements Criterion {
+public class RemoteResolveEntityCacheIdentifierCriterion implements Criterion {
- /** The request message. */
- @Nonnull private final TrustMarkStatusRequest request;
+ /** The trust mark identifier. */
+ @Nonnull private final RemoteResolveEntityCacheContainerIdentifier identifier;
/**
* Constructor.
*
- * @param requestMessage request message, must not be null
+ * @param id identifier, must not be null
*/
- public TrustMarkStatusRequestCriterion(@Nonnull final TrustMarkStatusRequest requestMessage) {
- request = Constraint.isNotNull(requestMessage, "Request cannot be null");
+ public RemoteResolveEntityCacheIdentifierCriterion(@Nonnull final RemoteResolveEntityCacheContainerIdentifier id) {
+ identifier = Constraint.isNotNull(id, "Identifier cannot be null");
}
/**
- * Get the request message.
+ * Get the trust mark identifier.
*
- * @return the request message
+ * @return the identifier
*/
- @Nonnull public TrustMarkStatusRequest getRequest() {
- return request;
+ @Nonnull public RemoteResolveEntityCacheContainerIdentifier getIdentifier() {
+ return identifier;
}
/** {@inheritDoc} */
@Override
public String toString() {
- return "TrustMarkStatusRequestCriterion [request=" + request + "]";
+ return "RemoteEntityCacheIdentifierCriterion [identifier=" + identifier + "]";
}
/** {@inheritDoc} */
@Override
public int hashCode() {
- return Objects.hash(request);
+ return Objects.hash(identifier);
}
/** {@inheritDoc} */
@@ -72,9 +71,8 @@ public class TrustMarkStatusRequestCriterion implements Criterion {
if (getClass() != obj.getClass()) {
return false;
}
- final TrustMarkStatusRequestCriterion other = (TrustMarkStatusRequestCriterion) obj;
- //TODO: proper equals-check
- return request.equals(other.request);
+ final RemoteResolveEntityCacheIdentifierCriterion other = (RemoteResolveEntityCacheIdentifierCriterion) obj;
+ return identifier.equals(other.identifier);
}
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityResponseContainer.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityResponseContainer.java
new file mode 100644
index 0000000..6f88635
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remoteresolver/RemoteResolveEntityResponseContainer.java
@@ -0,0 +1,69 @@
+/*
+ * 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.oidfed.metadata.cache.remoteresolver;
+
+import java.io.Serializable;
+import java.time.Instant;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.BaseExpirableEntityStatementContainer;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * A container class for metadata caches carrying ID and statement details related to Resolve Entity.
+ */
+public class RemoteResolveEntityResponseContainer extends BaseExpirableEntityStatementContainer
+ implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = 756269564456865370L;
+
+ /** Requested entity ID. */
+ @Nonnull private final RemoteResolveEntityCacheContainerIdentifier identifier;
+
+ /**
+ * Constructor.
+ *
+ * @param id identifier, must not be null
+ * @param resolveEntity resolve entity response parsed from the response
+ * @param validExpirationInstant expiration instant for valid statement, must not be null
+ * @param invalidExpirationInstant expiration instant for invalid statement, must not be null
+ */
+ public RemoteResolveEntityResponseContainer(@Nonnull final RemoteResolveEntityCacheContainerIdentifier id,
+ @Nullable final ResolveEntityResponse resolveEntity, @Nonnull final Instant validExpirationInstant,
+ @Nonnull final Instant invalidExpirationInstant) {
+ super(validExpirationInstant, resolveEntity, invalidExpirationInstant);
+ identifier = Constraint.isNotNull(id, "Identifier cannot be null");
+ }
+
+ /**
+ * Get entity ID.
+ *
+ * @return entity ID
+ */
+ @Nonnull @NotEmpty public RemoteResolveEntityCacheContainerIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull @NotEmpty public String getEntityId() {
+ return identifier.getSubject();
+ }
+
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkFetchingStrategy.java
new file mode 100644
index 0000000..eae898c
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkFetchingStrategy.java
@@ -0,0 +1,130 @@
+/*
+ * 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.oidfed.metadata.cache.tm;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
+import org.apache.hc.core5.net.URIBuilder;
+import org.slf4j.Logger;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMark;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.AbstractFederationEndpointResponseFetchingStrategy;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
+
+/**
+ * Default strategy for fetching trust mark via Trust Mark API for the request specified in the criteria set. The
+ * response is stored inside a {@link RemoteTrustMarkContainer}.
+ */
+ at ThreadSafeAfterInit
+public class DefaultTrustMarkFetchingStrategy
+ extends AbstractFederationEndpointResponseFetchingStrategy<TrustMarkCacheIdentifier, RemoteTrustMarkContainer> {
+
+ /** The JWT type header. */
+ @Nonnull
+ public static final JOSEObjectType JWT_TYPE_HEADER = new JOSEObjectType("trust-mark+jwt");
+
+ /** The HTTP response content type. */
+ @Nonnull public static final String HTTP_RESPONSE_CONTENT_TYPE = "application/" + JWT_TYPE_HEADER.toString();
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(DefaultTrustMarkFetchingStrategy.class);
+
+ /**
+ * Constructor.
+ */
+ public DefaultTrustMarkFetchingStrategy() {
+ setCriteriaToRequestDataStrategy(criteria -> {
+ final TrustMarkIdentifierCriterion identifierCriterion = criteria.get(TrustMarkIdentifierCriterion.class);
+ if (identifierCriterion == null) {
+ log.debug("No identifier criterion given, returning null");
+ return null;
+ }
+ return identifierCriterion.getIdentifier();
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
+ @Nonnull TrustMarkCacheIdentifier request) {
+ final HttpGet httpRequest = new HttpGet(request.getEndpoint());
+ final List<NameValuePair> nvps = new ArrayList<>();
+ nvps.add(new BasicNameValuePair("trust_mark_type", request.getTrustMarkType()));
+ nvps.add(new BasicNameValuePair("sub", request.getSubject()));
+ try {
+ final URI uri = new URIBuilder(httpRequest.getUri()).addParameters(nvps).build();
+ httpRequest.setUri(uri);
+ } catch (final URISyntaxException e) {
+ log.error("Could not create URI with the given parameters {}", request, e);
+ }
+ return httpRequest;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable protected RemoteTrustMarkContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
+ @Nonnull final TrustMarkCacheIdentifier request, @Nullable final ClassicHttpResponse response,
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
+ throws ProtocolException, IOException {
+ if (response != null) {
+ if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
+ log.warn("Unexpected content type: {}", response.getEntity().getContentType());
+ return new RemoteTrustMarkContainer(request, null, validExpiration, invalidExpiration);
+ }
+
+ try {
+ final SignedJWT jwt = SignedJWT.parse(EntityUtils.toString(response.getEntity()));
+ if (!JWT_TYPE_HEADER.equals(jwt.getHeader().getType())) {
+ log.warn("Unexpected JWT type header {}", jwt.getHeader().getType());
+ return new RemoteTrustMarkContainer(request, null, validExpiration, invalidExpiration);
+ }
+ assert objectMapper != null;
+ final TrustMark trustMark = TrustMark.parse(jwt, objectMapper);
+ return new RemoteTrustMarkContainer(
+ request, trustMark, validExpiration, invalidExpiration);
+ } catch (final JsonProcessingException e) {
+ log.warn("Could not deserialize entity statement payload from the response", e);
+ } catch (final ConstraintViolationException e) {
+ log.warn("Parsed entity configuration claims did not pass syntax validation", e);
+ } catch (java.text.ParseException e) {
+ log.warn("Could not parse JWT from the response", e);
+ }
+ } else {
+ log.debug("Unable to fetch trust mark: {} (null response)", request.getTrustMarkType());
+ }
+
+ return new RemoteTrustMarkContainer(request, null, validExpiration, invalidExpiration);
+ }
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkStatusFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkStatusFetchingStrategy.java
new file mode 100644
index 0000000..95d0450
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkStatusFetchingStrategy.java
@@ -0,0 +1,129 @@
+/*
+ * 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.oidfed.metadata.cache.tm;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
+import org.slf4j.Logger;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkStatus;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.AbstractFederationEndpointResponseFetchingStrategy;
+import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
+
+/**
+ * Default strategy for fetching trust mark status via Trust Mark Status API for the request specified in the criteria
+ * set. The status response is stored inside a {@link RemoteTrustMarkStatusContainer}.
+ */
+ at ThreadSafeAfterInit
+public class DefaultTrustMarkStatusFetchingStrategy
+ extends AbstractFederationEndpointResponseFetchingStrategy
+ <TrustMarkStatusCacheIdentifier, RemoteTrustMarkStatusContainer> {
+
+ /** The JWT type header. */
+ @Nonnull
+ public static final JOSEObjectType JWT_TYPE_HEADER = new JOSEObjectType("trust-mark-status-response+jwt");
+
+ /** The HTTP response content type. */
+ @Nonnull public static final String HTTP_RESPONSE_CONTENT_TYPE = "application/" + JWT_TYPE_HEADER.toString();
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(DefaultTrustMarkStatusFetchingStrategy.class);
+
+ /**
+ * Constructor.
+ */
+ public DefaultTrustMarkStatusFetchingStrategy() {
+ setCriteriaToRequestDataStrategy(criteria -> {
+ final TrustMarkStatusIdentifierCriterion identifierCriterion =
+ criteria.get(TrustMarkStatusIdentifierCriterion.class);
+ if (identifierCriterion == null) {
+ log.debug("No identifier criterion given, returning null");
+ return null;
+ }
+ return identifierCriterion.getIdentifier();
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
+ @Nonnull TrustMarkStatusCacheIdentifier identifier) {
+ final HttpPost httpRequest = new HttpPost(identifier.getEndpoint());
+ final List<NameValuePair> nvps = new ArrayList<>();
+ nvps.add(new BasicNameValuePair("trust_mark", identifier.getTrustMark().serialize()));
+ final UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
+ httpRequest.setEntity(urlEncodedFormEntity);
+ httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
+ return httpRequest;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable protected RemoteTrustMarkStatusContainer parseHttpResponse(@Nonnull final CriteriaSet criteria,
+ @Nonnull final TrustMarkStatusCacheIdentifier identifier, @Nullable final ClassicHttpResponse response,
+ @Nonnull final Instant validExpiration, @Nonnull final Instant invalidExpiration)
+ throws ProtocolException, IOException {
+ if (response != null) {
+ if (!HTTP_RESPONSE_CONTENT_TYPE.equals(response.getEntity().getContentType())) {
+ log.warn("Unexpected content type: {}", response.getEntity().getContentType());
+ return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, invalidExpiration);
+ }
+
+ try {
+ final SignedJWT jwt = SignedJWT.parse(EntityUtils.toString(response.getEntity()));
+ if (!JWT_TYPE_HEADER.equals(jwt.getHeader().getType())) {
+ log.warn("Unexpected JWT type header {}", jwt.getHeader().getType());
+ return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, invalidExpiration);
+ }
+ assert objectMapper != null;
+ final TrustMarkStatus trustMarkStatus = TrustMarkStatus.parse(jwt, objectMapper);
+ return new RemoteTrustMarkStatusContainer(
+ identifier, trustMarkStatus, validExpiration, invalidExpiration);
+ } catch (final JsonProcessingException e) {
+ log.warn("Could not deserialize trust mark status payload from the response", e);
+ } catch (final ConstraintViolationException e) {
+ log.warn("Parsed trust mark status claims did not pass syntax validation", e);
+ } catch (java.text.ParseException e) {
+ log.warn("Could not parse JWT from the response", e);
+ }
+ } else {
+ log.debug("Unable to fetch trust mark status: {} (null response)", identifier.getEndpoint());
+ }
+
+ return new RemoteTrustMarkStatusContainer(identifier, null, validExpiration, invalidExpiration);
+ }
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
similarity index 55%
rename from idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
index 6dddce0..5ca22ca 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/DefaultTrustMarkValidationCriteriaSetLookupFunction.java
@@ -12,45 +12,44 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm;
-import java.text.ParseException;
import java.util.List;
-import java.util.function.BiFunction;
+import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.opensaml.security.trust.TrustEngine;
import org.slf4j.Logger;
-import com.nimbusds.jwt.SignedJWT;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkStatusResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubjectEntityIDCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.BaseExpirableEntityStatementContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.IssuerEntityStatementCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteTrustChainsContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityStatementCriterion;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
-import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.resolver.CriteriaSet;
/**
- * Default signature validating filter for Trust Mark Status response. The signature validation is performed via
- * configurable {@link TrustEngine}.
+ * Default criteria set lookup strategy for {@link BaseExpirableEntityStatementContainer} that fetches the issuer
+ * entity statement via trust chain cache.
*/
@ThreadSafeAfterInit
-public class DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy
- extends AbstractTrustEngineSignatureValidationComponent
- implements BiFunction<TrustMarkStatusResponseContainer, MetadataFilterContext, TrustMarkStatusResponseContainer> {
+public class DefaultTrustMarkValidationCriteriaSetLookupFunction
+ extends AbstractIdentifiableInitializableComponent
+ implements Function<BaseExpirableEntityStatementContainer, CriteriaSet> {
/** Class logger. */
- @Nonnull private Logger log =
- LoggerFactory.getLogger(DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy.class);
+ @Nonnull
+ private Logger log = LoggerFactory.getLogger(DefaultTrustMarkValidationCriteriaSetLookupFunction.class);
/** Cache used to fetch the issuer entity configuration from. */
@NonnullAfterInit private MetadataCache<RemoteTrustChainsContainer> trustChainCache;
@@ -65,6 +64,7 @@ public class DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy
trustChainCache = Constraint.isNotNull(cache, "Trust Chain cache cannot be null");
}
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -72,59 +72,52 @@ public class DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy
if (trustChainCache == null) {
throw new ComponentInitializationException("Trust Chain cache cannot be null");
}
+
}
/** {@inheritDoc} */
@Override @Nullable
- public TrustMarkStatusResponseContainer apply(@Nullable final TrustMarkStatusResponseContainer response,
- @Nullable final MetadataFilterContext filterContext) {
- checkComponentActive();
- if (response == null) {
+ public CriteriaSet apply(@Nullable final BaseExpirableEntityStatementContainer metadataContainer) {
+ if (metadataContainer == null || metadataContainer.getEntityStatement() == null) {
+ log.debug("Entity statement is not found from the container, returning null");
return null;
}
- if (response.getResponse() instanceof TrustMarkStatusResponse successResponse) {
- final SignedJWT jwt = successResponse.getJWT();
- final String entityId;
- try {
- entityId = jwt.getJWTClaimsSet().getIssuer();
- } catch (final ParseException e) {
- log.error("Could not parse issuer entity ID value from the response", e);
- return null;
- }
- final EntityStatement issuerStatement = fetchIssuerStatement(entityId);
- if (issuerStatement == null) {
- return null;
- }
- log.trace("Starting signature validation of success response from {}", entityId);
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityStatementCriterion(issuerStatement));
- if (validateJwt(jwt, criteria, entityId)) {
- return response;
- }
- } else {
- log.trace("Ignoring signature validation for the error response");
- return response;
+ final EntityStatement statement = metadataContainer.getEntityStatement();
+ assert statement != null;
+ final SubjectEntityStatementCriterion subjectCriterion = new SubjectEntityStatementCriterion(statement);
+ final IssuerEntityStatementCriterion issuerCriterion = getIssuerCriterion(statement);
+ if (issuerCriterion == null) {
+ log.debug("Issuer statement could not be fetched, returning null");
+ return null;
}
- return null;
+ return new CriteriaSet(subjectCriterion, issuerCriterion);
}
/**
- * Fetch the issuer entity configuration from the trust chain metadata cache.
+ * Fetch the issuer entity configuration from the metadata cache and initialize the criterion.
*
- * @param issuer the issuer entity ID
+ * @param statement the entity statement whose issuer is fetched
* @return the issuer entity configuration, or null if could not be fetched
*/
- @Nullable protected EntityStatement fetchIssuerStatement(@Nonnull final String issuer) {
+ @Nullable protected IssuerEntityStatementCriterion getIssuerCriterion(
+ @Nonnull final EntityStatement statement) {
+ final String issuer = statement.getIssuer();
final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
try {
final List<RemoteTrustChainsContainer> result = trustChainCache.get(criteria);
if (!result.isEmpty()) {
final List<List<EntityStatement>> chains = result.get(0).getTrustChains();
- return chains.isEmpty() ? null : chains.get(0).get(0);
+ if (!chains.isEmpty()) {
+ final EntityStatement issuerStatement = chains.get(0).get(0);
+ assert issuerStatement != null;
+ return new IssuerEntityStatementCriterion(issuerStatement);
+ }
}
} catch (final MetadataCacheException e) {
log.debug("Error while fetching issuer trust chain for {}", issuer, e);
}
log.warn("Could not fetch entity configuration for {}", issuer);
return null;
+
}
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/RemoteTrustMarkContainer.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/RemoteTrustMarkContainer.java
new file mode 100644
index 0000000..87036da
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/RemoteTrustMarkContainer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.oidfed.metadata.cache.tm;
+
+import java.io.Serializable;
+import java.time.Instant;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMark;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.BaseExpirableEntityStatementContainer;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * A container class for metadata caches carrying ID and statement details related to Trust Mark.
+ */
+public class RemoteTrustMarkContainer extends BaseExpirableEntityStatementContainer implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = 756269369356865370L;
+
+ /** Requested entity ID. */
+ @Nonnull private final TrustMarkCacheIdentifier identifier;
+
+ /**
+ * Constructor.
+ *
+ * @param id identifier, must not be null
+ * @param trustMark trust mark parsed from the response
+ * @param validExpirationInstant expiration instant for valid statement, must not be null
+ * @param invalidExpirationInstant expiration instant for invalid statement, must not be null
+ */
+ public RemoteTrustMarkContainer(@Nonnull final TrustMarkCacheIdentifier id,
+ @Nullable final TrustMark trustMark, @Nonnull final Instant validExpirationInstant,
+ @Nonnull final Instant invalidExpirationInstant) {
+ super(validExpirationInstant, trustMark, invalidExpirationInstant);
+ identifier = Constraint.isNotNull(id, "Identifier cannot be null");
+ }
+
+ /**
+ * Get entity ID.
+ *
+ * @return entity ID
+ */
+ @Nonnull @NotEmpty public TrustMarkCacheIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull @NotEmpty public String getEntityId() {
+ return identifier.getSubject();
+ }
+
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/RemoteTrustMarkStatusContainer.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/RemoteTrustMarkStatusContainer.java
new file mode 100644
index 0000000..a2b5234
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/RemoteTrustMarkStatusContainer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.oidfed.metadata.cache.tm;
+
+import java.io.Serializable;
+import java.time.Instant;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkStatus;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.BaseExpirableEntityStatementContainer;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * A container class for metadata caches carrying ID and statement details related to Trust Mark status.
+ */
+public class RemoteTrustMarkStatusContainer extends BaseExpirableEntityStatementContainer implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = 756269369356884270L;
+
+ /** Requested entity ID. */
+ @Nonnull private final TrustMarkStatusCacheIdentifier identifier;
+
+ /**
+ * Constructor.
+ *
+ * @param id identifier, must not be null
+ * @param trustMarkStatus trust mark status parsed from the response
+ * @param validExpirationInstant expiration instant for valid statement, must not be null
+ * @param invalidExpirationInstant expiration instant for invalid statement, must not be null
+ */
+ public RemoteTrustMarkStatusContainer(@Nonnull final TrustMarkStatusCacheIdentifier id,
+ @Nullable final TrustMarkStatus trustMarkStatus, @Nonnull final Instant validExpirationInstant,
+ @Nonnull final Instant invalidExpirationInstant) {
+ super(validExpirationInstant, trustMarkStatus, invalidExpirationInstant);
+ identifier = Constraint.isNotNull(id, "Identifier cannot be null");
+ }
+
+ /**
+ * Get entity ID.
+ *
+ * @return entity ID
+ */
+ @Nonnull @NotEmpty public TrustMarkStatusCacheIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ /** {@inheritDoc} */
+ @Nonnull @NotEmpty public String getEntityId() {
+ return identifier.getEndpoint(); //TODO: revisit
+ }
+
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkRequest.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkCacheIdentifier.java
similarity index 66%
rename from idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkRequest.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkCacheIdentifier.java
index 2a080ab..67efa09 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/messaging/impl/TrustMarkRequest.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkCacheIdentifier.java
@@ -12,33 +12,35 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm;
-import java.net.URI;
+import java.io.Serializable;
+import java.util.Objects;
import javax.annotation.Nonnull;
import com.google.common.base.MoreObjects;
-import com.nimbusds.oauth2.sdk.Request;
-import com.nimbusds.oauth2.sdk.http.HTTPRequest;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.logic.Constraint;
/**
- * Request message to the OpenID federation Trust Mark endpoint.
+ * Default identifier for trust mark within {@link RemoteTrustMarkContainer}.
*/
-public class TrustMarkRequest implements Request {
+public class TrustMarkCacheIdentifier implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -4143516153785776493L;
/** The endpoint URI of the request. */
- @Nonnull private final URI endpointUri;
+ @Nonnull @NotEmpty private final String endpoint;
/** The identifier for the type of the Trust Mark. */
@Nonnull @NotEmpty private final String trustMarkType;
/** The entity ID of the Entity to which the Trust Mark is issued. */
@Nonnull @NotEmpty private final String subject;
-
+
/**
* Constructor.
*
@@ -46,23 +48,20 @@ public class TrustMarkRequest implements Request {
* @param type trust _mark type
* @param sub subject entity ID
*/
- public TrustMarkRequest(@Nonnull final URI uri, @Nonnull final String type, @Nonnull final String sub) {
- endpointUri = Constraint.isNotNull(uri, "Endpoint URI cannot be null");
+ public TrustMarkCacheIdentifier(@Nonnull @NotEmpty final String uri, @Nonnull @NotEmpty final String type,
+ @Nonnull @NotEmpty final String sub) {
+ endpoint = Constraint.isNotEmpty(uri, "Endpoint URI cannot be null");
trustMarkType = Constraint.isNotEmpty(type, "Trust Mark type cannot be null or empty");
subject = Constraint.isNotEmpty(sub, "Subject cannot be null or empty");
}
- /** {@inheritDoc} */
- @Override @Nonnull
- public URI getEndpointURI() {
- return endpointUri;
- }
-
- /** {@inheritDoc} */
- @Override
- public HTTPRequest toHTTPRequest() {
- //TODO
- return null;
+ /**
+ * Get the endpoint for the request.
+ *
+ * @return endpoint
+ */
+ @Nonnull @NotEmpty public String getEndpoint() {
+ return endpoint;
}
/**
@@ -89,25 +88,33 @@ public class TrustMarkRequest implements Request {
return MoreObjects.toStringHelper(this)
.add("subject", getSubject())
.add("trustMarkType", getTrustMarkType())
- .add("endpointURI", getEndpointURI())
+ .add("endpoint", getEndpoint())
.toString();
}
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return Objects.hash(endpoint, subject, trustMarkType);
+ }
+
/** {@inheritDoc} */
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
+
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
- final TrustMarkRequest other = (TrustMarkRequest) obj;
- return endpointUri.equals(other.endpointUri) && subject.equals(other.subject) &&
- trustMarkType.equals(other.trustMarkType);
+ final TrustMarkCacheIdentifier other = (TrustMarkCacheIdentifier) obj;
+ return endpoint.equals(other.endpoint) && subject.equals(other.subject)
+ && trustMarkType.equals(other.trustMarkType);
+
}
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkRequestCriterion.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkIdentifierCriterion.java
similarity index 56%
rename from idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkRequestCriterion.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkIdentifierCriterion.java
index 2629074..512a9f0 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkRequestCriterion.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkIdentifierCriterion.java
@@ -12,52 +12,51 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm;
import java.util.Objects;
import javax.annotation.Nonnull;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkRequest;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.resolver.Criterion;
/**
- * A {@link Criterion} representing request message to a Trust Mark API.
+ * A {@link Criterion} representing request message details to a Trust Mark API.
*/
-public class TrustMarkRequestCriterion implements Criterion {
+public class TrustMarkIdentifierCriterion implements Criterion {
- /** The request message. */
- @Nonnull private final TrustMarkRequest request;
+ /** The trust mark identifier. */
+ @Nonnull private final TrustMarkCacheIdentifier identifier;
/**
* Constructor.
*
- * @param requestMessage request message, must not be null
+ * @param id identifier, must not be null
*/
- public TrustMarkRequestCriterion(@Nonnull final TrustMarkRequest requestMessage) {
- request = Constraint.isNotNull(requestMessage, "Request cannot be null");
+ public TrustMarkIdentifierCriterion(@Nonnull final TrustMarkCacheIdentifier id) {
+ identifier = Constraint.isNotNull(id, "Identifier cannot be null");
}
/**
- * Get the request message.
+ * Get the trust mark identifier.
*
- * @return the request message
+ * @return the identifier
*/
- @Nonnull public TrustMarkRequest getRequest() {
- return request;
+ @Nonnull public TrustMarkCacheIdentifier getIdentifier() {
+ return identifier;
}
/** {@inheritDoc} */
@Override
public String toString() {
- return "TrustMarkRequestCriterion [request=" + request + "]";
+ return "TrustMarkIdentifierCriterion [identifier=" + identifier + "]";
}
/** {@inheritDoc} */
@Override
public int hashCode() {
- return Objects.hash(request);
+ return Objects.hash(identifier);
}
/** {@inheritDoc} */
@@ -72,8 +71,8 @@ public class TrustMarkRequestCriterion implements Criterion {
if (getClass() != obj.getClass()) {
return false;
}
- final TrustMarkRequestCriterion other = (TrustMarkRequestCriterion) obj;
- return request.equals(other.request);
+ final TrustMarkIdentifierCriterion other = (TrustMarkIdentifierCriterion) obj;
+ return identifier.equals(other.identifier);
}
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkStatusCacheIdentifier.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkStatusCacheIdentifier.java
new file mode 100644
index 0000000..3b56153
--- /dev/null
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkStatusCacheIdentifier.java
@@ -0,0 +1,103 @@
+/*
+ * 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.oidfed.metadata.cache.tm;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.base.MoreObjects;
+import com.nimbusds.jwt.SignedJWT;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * Request message to the OpenID federation Trust Mark Status endpoint.
+ */
+public class TrustMarkStatusCacheIdentifier implements Serializable {
+
+ /** Serial version UID. */
+ private static final long serialVersionUID = -4143643153785776493L;
+
+ /** The endpoint URI of the request. */
+ @Nonnull private final String endpoint;
+
+ /** The trust mark for the request. */
+ @Nonnull private final SignedJWT trustMark;
+
+ /**
+ * Constructor.
+ *
+ * @param uri endpoint URI
+ * @param jwt trust mark
+ */
+ public TrustMarkStatusCacheIdentifier(@Nonnull @NotEmpty final String uri, @Nonnull final SignedJWT jwt) {
+ endpoint = Constraint.isNotEmpty(uri, "Endpoint URI cannot be null");
+ trustMark = Constraint.isNotNull(jwt, "Trust Mark JWT cannot be null");
+ }
+
+ /**
+ * Get the endpoint URI of the request.
+ *
+ * @return endpoint
+ */
+ @Nonnull @NotEmpty public String getEndpoint() {
+ return endpoint;
+ }
+
+ /**
+ * Get the trust mark (serialized JWT) for the request.
+ *
+ * @return trust mark
+ */
+ @Nonnull @NotEmpty public SignedJWT getTrustMark() {
+ return trustMark;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("trustMark", getTrustMark().serialize())
+ .add("endpoint", getEndpoint())
+ .toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return Objects.hash(endpoint, trustMark.serialize());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TrustMarkStatusCacheIdentifier other = (TrustMarkStatusCacheIdentifier) obj;
+ return endpoint.equals(other.endpoint) && trustMark.serialize().equals(other.trustMark.serialize());
+ }
+
+}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusRequestCriterion.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkStatusIdentifierCriterion.java
similarity index 54%
rename from idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusRequestCriterion.java
rename to idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkStatusIdentifierCriterion.java
index f33a060..4a2f9f2 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/TrustMarkStatusRequestCriterion.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/tm/TrustMarkStatusIdentifierCriterion.java
@@ -12,52 +12,51 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
+package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm;
import java.util.Objects;
import javax.annotation.Nonnull;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkStatusRequest;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.resolver.Criterion;
/**
- * A {@link Criterion} representing request message to a Trust Mark Status API.
+ * A {@link Criterion} representing request message details to a Trust Mark Status API.
*/
-public class TrustMarkStatusRequestCriterion implements Criterion {
+public class TrustMarkStatusIdentifierCriterion implements Criterion {
- /** The request message. */
- @Nonnull private final TrustMarkStatusRequest request;
+ /** The trust mark status identifier. */
+ @Nonnull private final TrustMarkStatusCacheIdentifier identifier;
/**
* Constructor.
*
- * @param requestMessage request message, must not be null
+ * @param id identifier, must not be null
*/
- public TrustMarkStatusRequestCriterion(@Nonnull final TrustMarkStatusRequest requestMessage) {
- request = Constraint.isNotNull(requestMessage, "Request cannot be null");
+ public TrustMarkStatusIdentifierCriterion(@Nonnull final TrustMarkStatusCacheIdentifier id) {
+ identifier = Constraint.isNotNull(id, "Identifier cannot be null");
}
/**
- * Get the request message.
+ * Get the trust mark status identifier.
*
- * @return the request message
+ * @return the identifier
*/
- @Nonnull public TrustMarkStatusRequest getRequest() {
- return request;
+ @Nonnull public TrustMarkStatusCacheIdentifier getIdentifier() {
+ return identifier;
}
/** {@inheritDoc} */
@Override
public String toString() {
- return "TrustMarkStatusRequestCriterion [request=" + request + "]";
+ return "TrustMarkStatusIdentifierCriterion [identifier=" + identifier + "]";
}
/** {@inheritDoc} */
@Override
public int hashCode() {
- return Objects.hash(request);
+ return Objects.hash(identifier);
}
/** {@inheritDoc} */
@@ -72,9 +71,8 @@ public class TrustMarkStatusRequestCriterion implements Criterion {
if (getClass() != obj.getClass()) {
return false;
}
- final TrustMarkStatusRequestCriterion other = (TrustMarkStatusRequestCriterion) obj;
- //TODO: proper equals-check
- return request.equals(other.request);
+ final TrustMarkStatusIdentifierCriterion other = (TrustMarkStatusIdentifierCriterion) obj;
+ return identifier.equals(other.identifier);
}
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementFetchingStrategy.java
index 76af4b5..f726bfb 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementFetchingStrategy.java
@@ -49,6 +49,7 @@ import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.logic.ConstraintViolationException;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -73,6 +74,7 @@ public class DefaultSubordinateStatementFetchingStrategy
/** Class logger. */
@Nonnull private Logger log = LoggerFactory.getLogger(DefaultSubordinateStatementFetchingStrategy.class);
+ /** The entity configuration cache used for fetching issuer statement. */
@NonnullAfterInit private MetadataCache<RemoteEntityConfigurationContainer> entityConfigurationCache;
/**
@@ -94,11 +96,25 @@ public class DefaultSubordinateStatementFetchingStrategy
});
}
+ /**
+ * Set the entity configuration cache used for fetching issuer statement.
+ *
+ * @param cache entity configuration cache
+ */
public void setEntityConfigurationCache(@Nonnull final MetadataCache<RemoteEntityConfigurationContainer> cache) {
checkSetterPreconditions();
entityConfigurationCache = Constraint.isNotNull(cache, "Entity configuration cache cannot be null");
}
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+ if (entityConfigurationCache == null) {
+ throw new ComponentInitializationException("Entity configuration cache cannot be null");
+ }
+ }
+
/** {@inheritDoc} */
@Nullable protected ClassicHttpRequest initializeHttpRequest(@Nonnull final CriteriaSet criteria,
@Nonnull final SubordinateStatementCacheIdentifier id) {
@@ -106,8 +122,7 @@ public class DefaultSubordinateStatementFetchingStrategy
final List<RemoteEntityConfigurationContainer> issuerStatements;
try {
issuerStatements =
- entityConfigurationCache.get(new CriteriaSet(
- new SubjectEntityIDCriterion(issuerEntityId)));
+ entityConfigurationCache.get(new CriteriaSet(new SubjectEntityIDCriterion(issuerEntityId)));
} catch (final MetadataCacheException e) {
log.error("Could not resolve entity configuration for issuer {}", issuerEntityId, e);
return null;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementSignatureValidationCondition.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementSignatureValidationCondition.java
deleted file mode 100644
index 7ba3b68..0000000
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/ss/DefaultSubordinateStatementSignatureValidationCondition.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.oidfed.metadata.ss;
-
-import java.util.List;
-import java.util.function.BiPredicate;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.security.trust.TrustEngine;
-import org.slf4j.Logger;
-
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.AbstractTrustEngineSignatureValidationComponent;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubjectEntityIDCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.IssuerEntityStatementCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteEntityConfigurationContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteSubordinateStatementContainer;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityStatementCriterion;
-import net.shibboleth.oidc.metadata.cache.MetadataCache;
-import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
-import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.resolver.CriteriaSet;
-
-/**
- * Default signature validating filter for entity statement. The signature validation is performed via configurable
- * {@link TrustEngine}.
- */
- at ThreadSafeAfterInit
-public class DefaultSubordinateStatementSignatureValidationCondition
- extends AbstractTrustEngineSignatureValidationComponent
- implements BiPredicate<RemoteSubordinateStatementContainer, MetadataFilterContext> {
-
- /** Class logger. */
- @Nonnull private Logger log =
- LoggerFactory.getLogger(DefaultSubordinateStatementSignatureValidationCondition.class);
-
- @NonnullAfterInit private MetadataCache<RemoteEntityConfigurationContainer> entityConfigurationCache;
-
- public void setEntityConfigurationCache(@Nonnull final MetadataCache<RemoteEntityConfigurationContainer> cache) {
- checkSetterPreconditions();
- entityConfigurationCache = Constraint.isNotNull(cache, "Entity configuration cache cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean test(@Nullable final RemoteSubordinateStatementContainer responseContainer,
- @Nullable final MetadataFilterContext filterContext) {
- checkComponentActive();
- if (responseContainer == null) {
- return false;
- }
-
- final EntityStatement statement = responseContainer.getEntityStatement();
- if (statement != null ) {
- final String entityId = responseContainer.getIdentifier().getSubject();
- final String issuer = responseContainer.getIdentifier().getIssuer();
- assert issuer != null;
- log.trace("Validating subordinate statement for {}, issued by {}", entityId, issuer);
- final EntityStatement issuerStatement = fetchIssuerStatement(issuer);
- if (issuerStatement == null) {
- log.debug("Could not fetch issuer statement");
- return false;
- }
- final CriteriaSet criteria = new CriteriaSet();
- criteria.add(new IssuerEntityStatementCriterion(issuerStatement));
- criteria.add(new SubjectEntityStatementCriterion(statement));
-
- log.trace("Starting signature validation of entity configuration for {}", entityId);
- if (validateJwt(statement.getJwt(), criteria, entityId)) {
- return true;
- }
- return false;
- } else {
- log.debug("Ignoring signature check for the error response");
- }
- return true;
- }
-
- /**
- * Fetch the issuer entity configuration from the metadata cache.
- *
- * @param issuer the issuer entity ID
- * @return the issuer entity configuration, or null if could not be fetched
- */
- @Nullable protected EntityStatement fetchIssuerStatement(@Nonnull final String issuer) {
- final CriteriaSet criteria = new CriteriaSet(new SubjectEntityIDCriterion(issuer));
- try {
- final List<RemoteEntityConfigurationContainer> result = entityConfigurationCache.get(criteria);
- if (!result.isEmpty()) {
- return result.get(0).getEntityStatement();
- }
- } catch (final MetadataCacheException e) {
- log.debug("Error while fetching issuer entity configuration for {}", issuer, e);
- }
- log.warn("Could not fetch entity configuration for {}", issuer);
- return null;
- }
-}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java
index a4539c8..a21ba8e 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/CallResolveEntityApi.java
@@ -45,16 +45,16 @@ import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.id.ClientID;
import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ResolveEntityResponse;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatementHelper;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityRequestCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponseContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResolveEntityResponsePayload;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResponseContainerExpirationCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubjectEntityIDCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteEntityConfigurationContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.SubjectEntityStatementCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remoteresolver.RemoteResolveEntityCacheContainerIdentifier;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remoteresolver.RemoteResolveEntityCacheIdentifierCriterion;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remoteresolver.RemoteResolveEntityResponseContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.TrustedRemoteResolverEntity;
import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultPreSelectedTrustChainIDsLookupStrategy;
@@ -97,7 +97,7 @@ public class CallResolveEntityApi extends AbstractProfileAction {
@NonnullAfterInit private MetadataCache<RemoteEntityConfigurationContainer> entityConfigurationCache;
/** Cache containing responses from resolve entity APIs. */
- @NonnullAfterInit private MetadataCache<ResolveEntityResponseContainer> resolveEntityTrustChainMetadataCache;
+ @NonnullAfterInit private MetadataCache<RemoteResolveEntityResponseContainer> resolveEntityTrustChainMetadataCache;
/** Strategy used to obtain the client id value of the request. */
@NonnullAfterInit private Function<MessageContext, ClientID> clientIDLookupStrategy;
@@ -173,7 +173,7 @@ public class CallResolveEntityApi extends AbstractProfileAction {
}
public void setResolveEntityTrustChainMetadataCache(
- @Nonnull final MetadataCache<ResolveEntityResponseContainer> cache) {
+ @Nonnull final MetadataCache<RemoteResolveEntityResponseContainer> cache) {
checkSetterPreconditions();
resolveEntityTrustChainMetadataCache =
Constraint.isNotNull(cache, "ResolveEntityTrustChainMetadataCache cannot be null");
@@ -398,12 +398,13 @@ public class CallResolveEntityApi extends AbstractProfileAction {
log.warn("{} Could not fetch federation resolve endpoint for {}", getLogPrefix(), trustedEntity);
continue;
}
- final ResolveEntityRequest entityRequest = new ResolveEntityRequest(
- uri, clientId, List.copyOf(trustedEntity.getTrustAnchors()), List.of("openid_relying_party"));
+ final RemoteResolveEntityCacheContainerIdentifier entityRequest = new RemoteResolveEntityCacheContainerIdentifier(
+ uri.toString(), clientId, List.copyOf(trustedEntity.getTrustAnchors()),
+ List.of("openid_relying_party"));
final CriteriaSet criteriaSet = new CriteriaSet();
baseCriteriaSet.forEach(c -> criteriaSet.add(c));
- criteriaSet.add(new ResolveEntityRequestCriterion(entityRequest));
- final List<ResolveEntityResponseContainer> cacheResult;
+ criteriaSet.add(new RemoteResolveEntityCacheIdentifierCriterion(entityRequest));
+ final List<RemoteResolveEntityResponseContainer> cacheResult;
try {
cacheResult = resolveEntityTrustChainMetadataCache.get(criteriaSet);
} catch (final MetadataCacheException e) {
@@ -414,20 +415,12 @@ public class CallResolveEntityApi extends AbstractProfileAction {
log.debug("{} No data resolved for {} from {}", getLogPrefix(), clientId, trustedEntity);
continue;
}
- if (cacheResult.get(0).getResponse() instanceof ResolveEntityResponse successResponse) {
- final List<String> rawTrustChain;
- final Map<String, Object> rawMetadata;
- final List<Object> rawTrustMarks;
- try {
- rawTrustChain = successResponse.getJWT().getJWTClaimsSet().getStringListClaim("trust_chain");
- rawMetadata = successResponse.getJWT().getJWTClaimsSet().getJSONObjectClaim("metadata");
- rawTrustMarks = successResponse.getJWT().getJWTClaimsSet().getListClaim("trust_marks");
- } catch (final ParseException e) {
- log.error("{} Could not parse resolve entity response contents from {}", getLogPrefix(),
- trustedEntity, e);
- continue;
- }
- if (rawTrustChain == null || rawTrustChain.isEmpty() || rawMetadata == null || rawMetadata.isEmpty()) {
+ if (cacheResult.get(0).getEntityStatement() instanceof ResolveEntityResponse successResponse
+ && successResponse.getParsedPayload() instanceof ResolveEntityResponsePayload payload) {
+ final List<String> rawTrustChain = payload.getTrustChain();
+ final Map<String, Map<String, Object>> metadata = payload.getMetadata();
+ final List<Map<String,String>> rawTrustMarks = payload.getTrustMarks();
+ if (rawTrustChain == null || rawTrustChain.isEmpty() || metadata == null || metadata.isEmpty()) {
log.warn("{} Could not parse mandatory parameters from the response from {}", getLogPrefix(),
trustedEntity);
continue;
@@ -452,13 +445,6 @@ public class CallResolveEntityApi extends AbstractProfileAction {
getLogPrefix());
continue;
}
- final Map<String, Map<String, Object>> metadata = rawMetadata.entrySet().stream()
- .filter(entry -> entry.getKey() instanceof String && entry.getValue() instanceof Map<?,?>)
- .collect(Collectors.toMap(entry -> (String) entry.getKey(),
- entry -> ((Map<?,?>)entry.getValue()).entrySet().stream()
- .filter(e -> e.getKey() instanceof String)
- .collect(Collectors.toMap(e -> (String) e.getKey(), e -> e.getValue()))));
-
final List<Pair<List<EntityStatement>, Map<String,Map<String,Object>>>> policyCompliantChains =
new ArrayList<>();
policyCompliantChains.add(new Pair<>(chain, metadata));
@@ -510,7 +496,7 @@ public class CallResolveEntityApi extends AbstractProfileAction {
return;
} else {
log.debug("{} The response from {} was not a success response: {}", getLogPrefix(), trustedEntity,
- cacheResult.get(0).getResponse());
+ cacheResult.get(0).getEntityStatement());
continue;
}
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/DefaultTrustMarkFromMetadataCacheFetchingFunction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/DefaultTrustMarkFromMetadataCacheFetchingFunction.java
index 47ca881..4882312 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/DefaultTrustMarkFromMetadataCacheFetchingFunction.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/DefaultTrustMarkFromMetadataCacheFetchingFunction.java
@@ -29,13 +29,13 @@ import org.slf4j.Logger;
import com.fasterxml.jackson.databind.ObjectMapper;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkRequest;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkResponse;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatementHelper;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ResponseContainerExpirationCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkRequestCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkResponseContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMark;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.RemoteEntityConfigurationContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.RemoteTrustMarkContainer;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.TrustMarkCacheIdentifier;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.TrustMarkIdentifierCriterion;
import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.TrustedRemoteEntity;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
@@ -61,7 +61,7 @@ public class DefaultTrustMarkFromMetadataCacheFetchingFunction extends AbstractI
@NonnullAfterInit private MetadataCache<RemoteEntityConfigurationContainer> entityConfigurationCache;
/** Cache containing responses from Trust Mark APIs. */
- @NonnullAfterInit private MetadataCache<TrustMarkResponseContainer> trustMarkCache;
+ @NonnullAfterInit private MetadataCache<RemoteTrustMarkContainer> trustMarkCache;
/** JSON object mapper used for decoding JSON into Map. */
@NonnullAfterInit private ObjectMapper objectMapper;
@@ -100,7 +100,7 @@ public class DefaultTrustMarkFromMetadataCacheFetchingFunction extends AbstractI
*
* @param cache cache containing responses from Trust Mark APIs
*/
- public void setTrustMarkCache(@Nonnull final MetadataCache<TrustMarkResponseContainer> cache) {
+ public void setTrustMarkCache(@Nonnull final MetadataCache<RemoteTrustMarkContainer> cache) {
checkSetterPreconditions();
trustMarkCache = Constraint.isNotNull(cache, "Trust Mark cache cannot be null");
}
@@ -174,15 +174,16 @@ public class DefaultTrustMarkFromMetadataCacheFetchingFunction extends AbstractI
checkComponentActive();
final String entityId = trustedEntity.getEntityId();
final URI uri = EntityStatementHelper.fetchEndpointUriFromFederationEntity(entityConfigurationCache,
- entityId, "trust_mark_endpoint", Instant.now().plusSeconds(300)); //TODO
+ entityId, "trust_mark_endpoint");
if (uri == null) {
log.warn("Could not fetch trust mark endpoint for {}", entityId);
return null;
}
- final TrustMarkRequest trustMarkRequest = new TrustMarkRequest(uri, trustMarkType, subject);
- final CriteriaSet criteriaSet = new CriteriaSet(new TrustMarkRequestCriterion(trustMarkRequest));
+ final TrustMarkCacheIdentifier trustMarkIdentifier =
+ new TrustMarkCacheIdentifier(uri.toString(), trustMarkType, subject);
+ final CriteriaSet criteriaSet = new CriteriaSet(new TrustMarkIdentifierCriterion(trustMarkIdentifier));
criteriaSet.add(new ResponseContainerExpirationCriterion(Instant.now().plus(cachedLifetime)));
- final List<TrustMarkResponseContainer> cacheResult;
+ final List<RemoteTrustMarkContainer> cacheResult;
try {
cacheResult = trustMarkCache.get(criteriaSet);
} catch (final MetadataCacheException e) {
@@ -193,11 +194,11 @@ public class DefaultTrustMarkFromMetadataCacheFetchingFunction extends AbstractI
log.debug("No data resolved for {} from {}", trustMarkType, trustedEntity);
return null;
}
- if (cacheResult.get(0).getResponse() instanceof TrustMarkResponse successResponse) {
- return Map.of("trust_mark_type", trustMarkType, "trust_mark", successResponse.getJWT().serialize());
+ if (cacheResult.get(0).getEntityStatement() instanceof TrustMark trustMark) {
+ return Map.of("trust_mark_type", trustMarkType, "trust_mark", trustMark.getJwt().serialize());
} else {
log.debug("The response from {} was not a success response: {}", trustedEntity,
- cacheResult.get(0).getResponse());
+ cacheResult.get(0).getEntityStatement());
}
return null;
}
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 2d5aad1..ac97b8c 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
@@ -126,7 +126,7 @@
<bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ec.DefaultEntityConfigurationCriteriaSetLookupFunction"/>
</property>
</bean>
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ec.DefaultEntityConfigurationContentValidationCondition"
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
p:claimsValidator-ref="%{idp.oidfed.entityConfiguration.claimsValidator:shibboleth.oidfed.DefaultEntityConfigurationClaimsValidator}"/>
</util:list>
</property>
@@ -210,10 +210,14 @@
<bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementMetadataFilterStrategy">
<property name="validationConditions">
<util:list value-type="java.util.function.BiPredicate">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ss.DefaultSubordinateStatementSignatureValidationCondition"
- p:trustEngine-ref="shibboleth.oidfed.DefaultSubordinateStatementTrustEngine"
- p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"/>
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.ec.DefaultEntityConfigurationContentValidationCondition"
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementSignatureValidationCondition"
+ p:trustEngine-ref="shibboleth.oidfed.DefaultSubordinateStatementTrustEngine">
+ <property name="criteriaSetLookupStrategy">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementValidationCriteriaSetLookupFunction"
+ p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"/>
+ </property>
+ </bean>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
p:claimsValidator-ref="%{idp.oidfed.subordinateStatement.claimsValidator:shibboleth.oidfed.DefaultSubordinateStatementClaimsValidator}"/>
</util:list>
</property>
@@ -341,37 +345,74 @@
<bean id="shibboleth.oidfed.ResolveEntityTrustChainMetadataCacheBuilderSpec"
class="net.shibboleth.oidc.metadata.cache.impl.DynamicMetadataCacheBuilderSpec"
- p:minCacheDuration="%{idp.oidfed.entityConfiguration.maxRefreshDelay:PT1S}"
- p:maxCacheDuration="%{idp.oidfed.entityConfiguration.maxRefreshDelay:PT30S}">
+ p:minCacheDuration="%{idp.oidfed.cache.resolveEntity.minRefreshDelay:PT1M}"
+ p:maxCacheDuration="%{idp.oidfed.cache.resolveEntity.maxRefreshDelay:PT30M}"
+ p:metadataExpirationTimeStrategy-ref="DefaultResponseContainerExpirationTimeStrategy">
<property name="criteriaToIdentifierStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultResolveEntityRequestCriteriaToIdentifierStrategy" />
+ <bean parent="shibboleth.Functions.Expression" c:expression="#input?.get(T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remoteresolver.RemoteResolveEntityCacheIdentifierCriterion))?.getIdentifier()"/>
</property>
<property name="identifierExtractionStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultResolveEntityResponseIdentifierExtractionStrategy" />
- </property>
- <property name="metadataExpirationTimeStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultNimbusResponseContainerExpirationTimeStrategy"/>
+ <bean parent="shibboleth.Functions.Expression" c:expression="#input?.getIdentifier()"/>
</property>
<property name="metadataFilterStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultResolveEntityResponseSignatureValidationFilterStrategy"
- p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache">
- <property name="trustEngine">
- <bean class="net.shibboleth.oidc.security.impl.ExplicitKeySignedJWTTrustEngine">
- <constructor-arg index="0">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.security.credential.DefaultEntityConfigurationCredentialResolver" />
- </constructor-arg>
- <constructor-arg index="1">
- <bean class="net.shibboleth.oidc.security.credential.impl.BasicJOSEObjectCredentialResolver" />
- </constructor-arg>
- </bean>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementMetadataFilterStrategy">
+ <property name="validationConditions">
+ <util:list value-type="java.util.function.BiPredicate">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementSignatureValidationCondition"
+ p:trustEngine-ref="shibboleth.oidfed.DefaultSubordinateStatementTrustEngine">
+ <property name="criteriaSetLookupStrategy">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementValidationCriteriaSetLookupFunction"
+ p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"/>
+ </property>
+ </bean>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
+ p:claimsValidator-ref="%{idp.oidfed.remoteResolver.claimsValidator:shibboleth.oidfed.DefaultResolveEntityResponseClaimsValidator}"/>
+ </util:list>
</property>
</bean>
</property>
<property name="fetchStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultResolveEntityTrustChainFetchingStrategy"
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remoteresolver.DefaultResolveEntityTrustChainFetchingStrategy"
p:httpClient="#{getObject('shibboleth.oidfed.HttpClient') ?: getObject('shibboleth.InternalHttpClient')}"
p:httpClientSecurityParameters="#{getObject('shibboleth.oidfed.NonBrowser.HttpClientSecurityParameters')}"
- p:objectMapper-ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper"/>
+ p:objectMapper-ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper">
+ <property name="criteriaToValidContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.resolveEntity.validContainerLifetime:PT5M}" />
+ </constructor-arg>
+ </bean>
+ </property>
+ <property name="criteriaToInvalidContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.resolveEntity.invalidContainerLifetime:PT1M}" />
+ </constructor-arg>
+ </bean>
+ </property>
+ </bean>
+ </property>
+ </bean>
+
+ <bean id="shibboleth.oidfed.DefaultResolveEntityResponseClaimsValidator"
+ class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator">
+ <property name="claimValidators">
+ <util:list value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.IssuedAtClaimsValidator"
+ p:clockSkew="%{idp.policy.clockSkew:PT1M}"
+ p:messageLifetime="%{idp.policy.messageLifetime:PT1M}"
+ p:requiredRule="true" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="iss" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="sub" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExpiryClaimsValidator"
+ p:clockSkew="%{idp.policy.clockSkew:PT1M}" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="metadata" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="trust_chain" />
+ </util:list>
</property>
</bean>
@@ -430,18 +471,65 @@
<bean parent="shibboleth.Functions.Expression" c:expression="#input?.getRequest().getTrustMark().serialize()"/>
</property>
<property name="criteriaToIdentifierStrategy">
- <bean parent="shibboleth.Functions.Expression" c:expression="#input?.get(T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkRequestCriterion))?.getRequest().getTrustMark().serialize()"/>
+ <bean parent="shibboleth.Functions.Expression" c:expression="#input?.get(T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.TrustMarkStatusIdentifierCriterion))?.getIdentifier()"/>
</property>
<property name="metadataFilterStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultTrustMarkStatusResponseSignatureValidationFilterStrategy"
- p:trustChainCache-ref="shibboleth.oidfed.TrustChainMetadataCache"
- p:trustEngine-ref="shibboleth.oidfed.DefaultEntityConfigurationTrustEngine"/>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementMetadataFilterStrategy">
+ <property name="validationConditions">
+ <util:list value-type="java.util.function.BiPredicate">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementSignatureValidationCondition"
+ p:trustEngine-ref="shibboleth.oidfed.DefaultSubordinateStatementTrustEngine">
+ <property name="criteriaSetLookupStrategy">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.DefaultTrustMarkValidationCriteriaSetLookupFunction"
+ p:trustChainCache-ref="shibboleth.oidfed.TrustChainMetadataCache"/>
+ </property>
+ </bean>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
+ p:claimsValidator-ref="%{idp.oidfed.trustMarkStatus.claimsValidator:shibboleth.oidfed.DefaultTrustMarkStatusClaimsValidator}"/>
+ </util:list>
+ </property>
+ </bean>
</property>
<property name="fetchStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultTrustMarkStatusFetchingStrategy"
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.DefaultTrustMarkStatusFetchingStrategy"
p:httpClient="#{getObject('shibboleth.oidfed.HttpClient') ?: getObject('shibboleth.InternalHttpClient')}"
p:httpClientSecurityParameters="#{getObject('shibboleth.oidfed.NonBrowser.HttpClientSecurityParameters')}"
- p:objectMapper-ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper"/>
+ p:objectMapper-ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper">
+ <property name="criteriaToValidContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.trustMarkStatus.validContainerLifetime:PT5M}" />
+ </constructor-arg>
+ </bean>
+ </property>
+ <property name="criteriaToInvalidContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.trustMarkStatus.invalidContainerLifetime:PT1M}" />
+ </constructor-arg>
+ </bean>
+ </property>
+ </bean>
+ </property>
+ </bean>
+
+ <bean id="shibboleth.oidfed.DefaultTrustMarkStatusClaimsValidator"
+ class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator">
+ <property name="claimValidators">
+ <util:list value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.IssuedAtClaimsValidator"
+ p:clockSkew="%{idp.policy.clockSkew:PT1M}"
+ p:messageLifetime="%{idp.policy.messageLifetime:PT1M}"
+ p:requiredRule="true" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="iss" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExpiryClaimsValidator"
+ p:clockSkew="%{idp.policy.clockSkew:PT1M}" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="trust_mark" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="status" />
+ </util:list>
</property>
</bean>
@@ -455,26 +543,71 @@
<bean id="shibboleth.oidfed.TrustMarkMetadataCacheBuilderSpec"
class="net.shibboleth.oidc.metadata.cache.impl.DynamicMetadataCacheBuilderSpec"
p:minCacheDuration="%{idp.oidfed.cache.trustMark.minRefreshDelay:PT1H}"
- p:maxCacheDuration="%{idp.oidfed.cache.trustMark.maxRefreshDelay:PT24H}">
+ p:maxCacheDuration="%{idp.oidfed.cache.trustMark.maxRefreshDelay:PT24H}"
+ p:metadataExpirationTimeStrategy-ref="DefaultResponseContainerExpirationTimeStrategy">
<property name="identifierExtractionStrategy">
- <bean parent="shibboleth.Functions.Expression" c:expression="#input?.getRequestMessage().toString()"/>
+ <bean parent="shibboleth.Functions.Expression" c:expression="#input?.getIdentifier()"/>
</property>
<property name="criteriaToIdentifierStrategy">
- <bean parent="shibboleth.Functions.Expression" c:expression="#input?.get(T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.TrustMarkRequestCriterion))?.getRequest().toString()"/>
+ <bean parent="shibboleth.Functions.Expression" c:expression="#input?.get(T(net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.TrustMarkIdentifierCriterion))?.getIdentifier()"/>
</property>
<property name="metadataFilterStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultTrustMarkResponseSignatureValidationFilterStrategy"
- p:trustChainCache-ref="shibboleth.oidfed.TrustChainMetadataCache"
- p:trustEngine-ref="shibboleth.oidfed.DefaultEntityConfigurationTrustEngine"/>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementMetadataFilterStrategy">
+ <property name="validationConditions">
+ <util:list value-type="java.util.function.BiPredicate">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementSignatureValidationCondition"
+ p:trustEngine-ref="shibboleth.oidfed.DefaultSubordinateStatementTrustEngine">
+ <property name="criteriaSetLookupStrategy">
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.DefaultTrustMarkValidationCriteriaSetLookupFunction"
+ p:trustChainCache-ref="shibboleth.oidfed.TrustChainMetadataCache"/>
+ </property>
+ </bean>
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultEntityStatementContentValidationCondition"
+ p:claimsValidator-ref="%{idp.oidfed.trustMark.claimsValidator:shibboleth.oidfed.DefaultTrustMarkClaimsValidator}"/>
+ </util:list>
+ </property>
+ </bean>
</property>
<property name="fetchStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultTrustMarkFetchingStrategy"
+ <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.DefaultTrustMarkFetchingStrategy"
p:httpClient="#{getObject('shibboleth.oidfed.HttpClient') ?: getObject('shibboleth.InternalHttpClient')}"
p:httpClientSecurityParameters="#{getObject('shibboleth.oidfed.NonBrowser.HttpClientSecurityParameters')}"
- p:objectMapper-ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper"/>
+ p:objectMapper-ref="shibboleth.oidfed.JWTPayloadJSONObjectMapper">
+ <property name="criteriaToValidContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.trustMark.validContainerLifetime:PT5M}" />
+ </constructor-arg>
+ </bean>
+ </property>
+ <property name="criteriaToInvalidContainerLifetimeStrategy">
+ <bean parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <bean class="java.time.Duration" factory-method="parse" c:_0="%{idp.oidfed.cache.trustMark.invalidContainerLifetime:PT1M}" />
+ </constructor-arg>
+ </bean>
+ </property>
+ </bean>
</property>
- <property name="metadataExpirationTimeStrategy">
- <bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.DefaultNimbusResponseContainerExpirationTimeStrategy"/>
+ </bean>
+
+ <bean id="shibboleth.oidfed.DefaultTrustMarkClaimsValidator"
+ class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator">
+ <property name="claimValidators">
+ <util:list value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator">
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.IssuedAtClaimsValidator"
+ p:clockSkew="%{idp.policy.clockSkew:PT1M}"
+ p:messageLifetime="%{idp.policy.messageLifetime:PT1M}"
+ p:requiredRule="true" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="iss" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="sub" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.ExpiryClaimsValidator"
+ p:clockSkew="%{idp.policy.clockSkew:PT1M}" />
+ <bean class="net.shibboleth.oidc.security.jwt.claims.impl.RequiredClaimsValidator"
+ p:requiredClaims="trust_mark_type" />
+ </util:list>
</property>
</bean>
@@ -605,7 +738,10 @@
</property>
</bean>
- <bean id="DefaultTrustMarkClaimsValidationLookupStrategy" parent="shibboleth.Functions.Constant">
+ <bean id="DefaultTrustMarkClaimsValidationLookupStrategy" parent="shibboleth.Functions.Constant"
+ c:target-ref="shibboleth.oidfed.DefaultTrustMarkClaimsValidator" />
+
+ <bean id="DefaultDelegatedTrustMarkClaimsValidationLookupStrategy" parent="shibboleth.Functions.Constant">
<constructor-arg name="target">
<bean class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator">
<property name="claimValidators">
@@ -628,6 +764,7 @@
</constructor-arg>
</bean>
+
<bean id="shibboleth.oidfed.DefaultPreSelectedTrustChainIDsLookupStrategy"
class="net.shibboleth.idp.plugin.oidc.op.oidfed.profile.navigate.DefaultPreSelectedTrustChainIDsLookupStrategy">
<property name="profileIdLookupStrategy">
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 1d6f6f1..370dc07 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
@@ -107,7 +107,7 @@
scope="prototype"
p:trustChainCache-ref="#{'%{idp.oidfed.authorize.TrustChainMetadataCache:shibboleth.oidfed.TrustChainMetadataCache}'.trim()}"
p:trustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.TrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
- p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
+ p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultDelegatedTrustMarkClaimsValidationLookupStrategy')}"
p:trustEngine-ref="shibboleth.oidfed.DefaultEntityConfigurationTrustEngine"
p:delegationTrustEngine-ref="shibboleth.oidfed.DefaultDelegatedTrustMarkTrustEngine">
<property name="trustChainTrustMarksParsingStrategy">
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 c9c63b1..142e58a 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
@@ -215,7 +215,7 @@
scope="prototype"
p:trustChainCache-ref="#{'%{idp.oidfed.register.TrustChainMetadataCache:shibboleth.oidfed.TrustChainMetadataCache}'.trim()}"
p:trustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.TrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
- p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
+ p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultDelegatedTrustMarkClaimsValidationLookupStrategy')}"
p:trustEngine-ref="shibboleth.oidfed.DefaultEntityConfigurationTrustEngine"
p:delegationTrustEngine-ref="shibboleth.oidfed.DefaultDelegatedTrustMarkTrustEngine">
<property name="trustChainTrustMarksParsingStrategy">
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
index c5a6652..0bea4da 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
@@ -128,7 +128,7 @@
scope="prototype"
p:trustChainCache-ref="#{'%{idp.oidfed.resolve-entity.TrustChainMetadataCache:shibboleth.oidfed.TrustChainMetadataCache}'.trim()}"
p:trustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.TrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
- p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultTrustMarkClaimsValidationLookupStrategy')}"
+ p:delegatedTrustMarkClaimsValidationLookupStrategy="#{getObject('shibboleth.oidfed.DelegatedTrustMarkClaimsValidationLookupStrategy') ?: getObject('DefaultDelegatedTrustMarkClaimsValidationLookupStrategy')}"
p:trustEngine-ref="shibboleth.oidfed.DefaultEntityConfigurationTrustEngine"
p:delegationTrustEngine-ref="shibboleth.oidfed.DefaultDelegatedTrustMarkTrustEngine">
<property name="trustChainTrustMarksParsingStrategy">
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
index 25729f6..867a617 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/EntityConfigurationFlowTest.java
@@ -42,7 +42,7 @@ import com.nimbusds.openid.connect.sdk.federation.registration.ClientRegistratio
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import net.shibboleth.idp.plugin.oidc.op.oidfed.TrustChainTestUtil;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.TrustMarkResponse;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.tm.DefaultTrustMarkFetchingStrategy;
import net.shibboleth.shared.collection.CollectionSupport;
/**
@@ -75,7 +75,8 @@ public class EntityConfigurationFlowTest extends AbstractFederationFlowTest {
+ URLEncoder.encode(dynamicTrustMarkType, Charset.forName("UTF-8"))
+ "&sub=" + URLEncoder.encode(issuer, Charset.forName("UTF-8"));
mapResponse(trustMarkUrl,
- mockResponse(200, TrustMarkResponse.HTTP_RESPONSE_CONTENT_TYPE.toString(), trustMark));
+ mockResponse(200, DefaultTrustMarkFetchingStrategy.HTTP_RESPONSE_CONTENT_TYPE.toString(),
+ trustMark));
} catch (UnsupportedOperationException | IOException e) {
Assert.fail("Could not initialize mock HTTP client", e);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list