[java-idp-oidc] 01/04: JOIDC-222 - Support for OpenID Federation

Henri Mikkonen henri.mikkonen at iki.fi
Fri Aug 8 12:18:23 UTC 2025


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

hjmikkon pushed a commit to branch dev/JOIDC-222
in repository java-idp-oidc.

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

commit 9a6ca379f5b731e064aebccd3fd92ca76c25e4b0
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Wed Aug 6 12:14:51 2025 +0300

    JOIDC-222 - Support for OpenID Federation
    
    https://shibboleth.atlassian.net/browse/JOIDC-222
    
    Moved general-purpose functions to EntityStatementHelper
---
 .../ExplicitClientRegistrationRequestDecoder.java  | 37 +++++-------------
 .../DefaultEntityStatementFetchingStrategy.java    |  7 ++--
 .../op/oidfed/metadata/EntityStatementHelper.java  | 45 ++++++++++++++++++++++
 3 files changed, 57 insertions(+), 32 deletions(-)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java
index da8276e8..6d737a05 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/decoding/impl/ExplicitClientRegistrationRequestDecoder.java
@@ -28,7 +28,6 @@ import org.slf4j.Logger;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.MoreObjects;
-import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.oauth2.sdk.http.HTTPRequest;
 import com.nimbusds.oauth2.sdk.http.JakartaServletUtils;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
@@ -37,6 +36,7 @@ import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.idp.plugin.oidc.op.decoding.impl.RequestUtil;
 import net.shibboleth.idp.plugin.oidc.op.oauth2.decoding.impl.BaseOAuth2RequestDecoder;
 import net.shibboleth.idp.plugin.oidc.op.oidfed.messaging.impl.ExplicitClientRegistrationRequest;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatementHelper;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
@@ -47,7 +47,8 @@ import net.shibboleth.shared.primitive.LoggerFactory;
  * 
  * @since 4.3.0
  */
-public class ExplicitClientRegistrationRequestDecoder extends BaseOAuth2RequestDecoder<ExplicitClientRegistrationRequest> {
+public class ExplicitClientRegistrationRequestDecoder
+    extends BaseOAuth2RequestDecoder<ExplicitClientRegistrationRequest> {
 
     /** Class logger. */
     @Nonnull
@@ -92,7 +93,8 @@ public class ExplicitClientRegistrationRequestDecoder extends BaseOAuth2RequestD
             }
             final String contentType = request.getContentType();
             if ("application/entity-statement+jwt".equals(contentType)) {
-                final EntityStatement entityConfiguration = deserializeEntityStatement(httpRequest.getQuery());
+                final EntityStatement entityConfiguration =
+                        EntityStatementHelper.deserializeEntityStatement(httpRequest.getQuery());
                 if (entityConfiguration == null) {
                     throw new MessageDecodingException("Could not deserialize entity configuration");
                 }
@@ -102,7 +104,7 @@ public class ExplicitClientRegistrationRequestDecoder extends BaseOAuth2RequestD
                 final TypeReference<List<String>> typeReference = new TypeReference<List<String>>() {};
                 final List<String> strings = objectMapper.readValue(httpRequest.getQuery(), typeReference);
                 final List<EntityStatement> trustChain = strings.stream()
-                        .map(string -> deserializeEntityStatement(string))
+                        .map(string -> EntityStatementHelper.deserializeEntityStatement(string))
                         .filter(Objects::nonNull)
                         .toList();
                 if (trustChain == null || trustChain.isEmpty()) {
@@ -123,32 +125,11 @@ public class ExplicitClientRegistrationRequestDecoder extends BaseOAuth2RequestD
     @Override
     protected String getMessageToLog(@Nullable final ExplicitClientRegistrationRequest message) {
         return message == null ? null : MoreObjects.toStringHelper(this).omitNullValues()
-                .add("entityConfiguration", getSerializedEntityStatement(message.getEntityConfiguration()))
-                .add("trustChain", getSerializedTrustChain(message.getTrustChain()))
+                .add("entityConfiguration", EntityStatementHelper.getSerializedEntityStatement(
+                        message.getEntityConfiguration()))
+                .add("trustChain", EntityStatementHelper.getSerializedTrustChain(message.getTrustChain()))
                 .add("endpointURI", getEndpointURI(message))
                 .toString();
     }
 
-    @Nullable protected EntityStatement deserializeEntityStatement(@Nullable final String serialized) {
-        try {
-            if (serialized != null) {
-                return EntityStatement.parse(serialized);
-            }
-        } catch (final ParseException e) {
-            log.trace("Could not construct entity statement from {}", serialized, e);
-        }
-        log.warn("Could not deserialize entity statement {}", serialized);
-        return null;
-    }
-
-    @Nullable
-    protected String getSerializedTrustChain(@Nullable final List<EntityStatement> trustChain) {
-        return trustChain == null ? null :
-            String.join(",", trustChain.stream().map(es -> es.getSignedStatement().serialize()).toList());
-    }
-
-    @Nullable
-    protected String getSerializedEntityStatement(@Nullable final EntityStatement entityStatement) {
-        return entityStatement == null ? null : entityStatement.getSignedStatement().serialize();
-    }
 }
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityStatementFetchingStrategy.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityStatementFetchingStrategy.java
index 0493ca47..acf05790 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityStatementFetchingStrategy.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/DefaultEntityStatementFetchingStrategy.java
@@ -28,12 +28,12 @@ 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.HttpStatus;
+import org.apache.hc.core5.http.ParseException;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
 import org.opensaml.security.httpclient.HttpClientSecuritySupport;
 import org.slf4j.Logger;
 
-import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
 
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
@@ -139,14 +139,13 @@ public class DefaultEntityStatementFetchingStrategy extends AbstractIdentifiable
             assert scheme != null;
             HttpClientSecuritySupport.checkTLSCredentialEvaluated(httpContext, scheme);
             if (response.getCode() == HttpStatus.SC_OK) {
-                return EntityStatement.parse(EntityUtils.toString(response.getEntity()));
+                return EntityStatementHelper.deserializeEntityStatement(EntityUtils.toString(response.getEntity()));
             } else {
                 log.debug("Unable to fetch entity configuration from URI: {} (HTTP status {})", uri,
                         response.getCode());
                 return null;
             }
-        } catch (final org.apache.hc.core5.http.ParseException | URISyntaxException | IOException | 
-                ParseException e) {
+        } catch (final ParseException | URISyntaxException | IOException e) {
             log.debug("Unable to fetch entity statement from URI: {}", uri, e);
         }
 
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java
index fc2491cf..a80a5848 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/EntityStatementHelper.java
@@ -14,9 +14,11 @@
 
 package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata;
 
+import java.util.List;
 import java.util.Map;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
 
@@ -24,6 +26,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.type.MapType;
+import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
 
 import net.shibboleth.shared.collection.CollectionSupport;
@@ -115,4 +118,46 @@ public class EntityStatementHelper {
             @Nonnull final EntityStatement entityStatement) {
         return parseClaimAsMapOfMaps(objectMapper, entityStatement, "metadata");
     }
+
+    /**
+     * Deseriealize the given string into an entity statement.
+     * 
+     * @param serialized input string
+     * @return entity statement
+     */
+    @Nullable public static EntityStatement deserializeEntityStatement(@Nullable final String serialized) {
+        try {
+            if (serialized != null) {
+                return EntityStatement.parse(serialized);
+            }
+        } catch (final ParseException e) {
+            log.trace("Could not construct entity statement from {}", serialized, e);
+        }
+        log.warn("Could not deserialize entity statement {}", serialized);
+        return null;
+    }
+
+    /**
+     * Serialize the given trust chain into a comma-separated list of strings.
+     * 
+     * @param trustChain input trust chain
+     * @return serialized trust chain
+     */
+    @Nullable
+    public static String getSerializedTrustChain(@Nullable final List<EntityStatement> trustChain) {
+        return trustChain == null ? null :
+            String.join(",", trustChain.stream().map(es -> es.getSignedStatement().serialize()).toList());
+    }
+
+    /**
+     * Serialize the given entity statement into a string.
+     * 
+     * @param entityStatement input entity statement
+     * @return serialized entity statement
+     */
+    @Nullable
+    public static String getSerializedEntityStatement(@Nullable final EntityStatement entityStatement) {
+        return entityStatement == null ? null : entityStatement.getSignedStatement().serialize();
+    }
+
 }
\ No newline at end of file

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


More information about the commits mailing list