[java-oidfed-common] branch main updated: Also store trust mark expiration times into the client information extension

Codeberg noreply at shibboleth.net
Mon Oct 5 13:43:53 UTC 2026


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

codeberg pushed a commit to branch main
in repository java-oidfed-common.

View the commit online:
https://codeberg.org/Shibboleth/java-oidfed-common/commit/f94cab943665874344bbdaeb3416ff7025018572

The following commit(s) were added to refs/heads/main by this push:
     new f94cab9  Also store trust mark expiration times into the client information extension
f94cab9 is described below

commit f94cab943665874344bbdaeb3416ff7025018572
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Mon Oct 5 16:43:16 2026 +0300

    Also store trust mark expiration times into the client information extension
---
 .../support/ClientInformationExtensionSupport.java | 42 ++++++++++++++++++--
 .../metadata/util/EntityStatementHelper.java       | 45 ++++++++++++++++++++++
 2 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/oidfed-common-api/src/main/java/net/shibboleth/oidfed/support/ClientInformationExtensionSupport.java b/oidfed-common-api/src/main/java/net/shibboleth/oidfed/support/ClientInformationExtensionSupport.java
index 42584b8..f9e5407 100644
--- a/oidfed-common-api/src/main/java/net/shibboleth/oidfed/support/ClientInformationExtensionSupport.java
+++ b/oidfed-common-api/src/main/java/net/shibboleth/oidfed/support/ClientInformationExtensionSupport.java
@@ -14,6 +14,7 @@
 
 package net.shibboleth.oidfed.support;
 
+import java.time.Instant;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -26,6 +27,7 @@ import javax.annotation.Nullable;
 import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.collection.Pair;
 
 /**
  * Helper methods for our client information extensions related to OpenID federation.
@@ -71,12 +73,13 @@ public class ClientInformationExtensionSupport {
     }
 
     /**
-     * Parse validated trust mark IDs from the given client information..
+     * Parse validated trust mark IDs from the given client information. The {@link Pair} is transformed from a map,
+     * as added by {@link #addValidatedTrustMarkIds(OIDCClientInformation, Map)}.
      * 
      * @param clientInformation client information
      * @return validated trust mark IDs
      */
-    @Nullable public static Map<String, List<String>> parseValidatedTrustMarkIds(
+    @Nullable public static Map<String, List<Pair<String,Instant>>> parseValidatedTrustMarkIds(
             @Nonnull final OIDCClientInformation clientInformation) {
         return Optional.ofNullable(clientInformation.getOIDCMetadata().getCustomField(KEY_VALIDATED_TRUST_MARK_IDS))
                 .filter(Map.class::isInstance)
@@ -87,9 +90,42 @@ public class ClientInformationExtensionSupport {
                         .collect(Collectors.toMap(entry -> entry.getKey().toString(),
                                 entry -> ((List<?>) entry.getValue()).stream()
                                 .filter(Objects::nonNull)
-                                .map(Objects::toString)
+                                .filter(Map.class::isInstance)
+                                .map(obj -> (Map<?,?>) obj)
+                                .map(pairMap -> {
+                                    if (pairMap.get("type") instanceof String string) {
+                                        if (pairMap.get("exp") instanceof Long expiration) {
+                                            return new Pair<>(string, Instant.ofEpochMilli(expiration));
+                                        }
+                                    }
+                                    return null;
+                                })
+                                .filter(Objects::nonNull)
                                 .toList())))
                 .orElse(null);
     }
 
+    /**
+     * Adds the given map of validated trust mark IDs into the given client information object. The {@link Pair} is
+     * transformed into a map.
+     * 
+     * @param clientInformation client information
+     * @param trustMarkIds validated trust mark IDs
+     */
+    public static void addValidatedTrustMarkIds(@Nonnull final OIDCClientInformation clientInformation,
+            @Nonnull final Map<String, List<Pair<String, Instant>>> trustMarkIds) {
+        final Map<String, List<Map<String, Object>>> result = trustMarkIds.entrySet().stream()
+                .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().stream()
+                        .filter(pair -> pair.getFirst() != null && pair.getSecond() != null)
+                        .map(pair -> {
+                            final Object type = pair.getFirst();
+                            final Instant exp = pair.getSecond();
+                            assert exp != null;
+                            return Map.of(
+                                "type", type,
+                                "exp", exp.toEpochMilli());
+                        })
+                        .toList()));
+        clientInformation.getOIDCMetadata().setCustomField(KEY_VALIDATED_TRUST_MARK_IDS, result);
+    }
 }
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/util/EntityStatementHelper.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/util/EntityStatementHelper.java
index 65f2351..21b3154 100644
--- a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/util/EntityStatementHelper.java
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/metadata/util/EntityStatementHelper.java
@@ -15,10 +15,13 @@
 package net.shibboleth.oidfed.metadata.util;
 
 import java.text.ParseException;
+import java.time.Duration;
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 import javax.annotation.Nonnull;
@@ -34,9 +37,11 @@ import com.nimbusds.jwt.SignedJWT;
 import net.shibboleth.oidfed.metadata.EntityConfiguration;
 import net.shibboleth.oidfed.metadata.EntityStatement;
 import net.shibboleth.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.oidfed.metadata.TrustMark;
 import net.shibboleth.oidfed.metadata.impl.EntityConfigurationImpl;
 import net.shibboleth.oidfed.metadata.impl.SubordinateStatementImpl;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
@@ -232,4 +237,44 @@ public class EntityStatementHelper {
         }
         return true;
     }
+
+    /**
+     * Parse the given map of trust marks into map of pairs containing the trust mark type and its expiration time.
+     * The expiration time is taken from the trust mark if it exists, or via given maximum lifetime if not. If both
+     * are defined, the one that expires earlier is used.
+     * 
+     * @param trustMarks map of trust marks per entity ID
+     * @param maximumLifetime maximum lifetime for trust marks
+     * @return map of trust mark types and their expiration per entity ID
+     */
+    @Nullable public static Map<String,List<Pair<String,Instant>>> parseExpirableTrustMarkIds(
+            @Nullable final Map<String, List<TrustMark>> trustMarks, @Nonnull final Duration maximumLifetime) {
+        if (trustMarks == null || trustMarks.isEmpty()) {
+            log.debug("No trust marks given, returning null");
+            return null;
+        }
+        final Map<String,List<Pair<String,Instant>>> result = new HashMap<>();
+        final Instant maximumExpiration = Instant.now().plus(maximumLifetime);
+        for (final String entity : trustMarks.keySet()) {
+            final List<Pair<String,Instant>> pairs = new ArrayList<>();
+            final List<TrustMark> entityTrustMarks = trustMarks.get(entity);
+            if (entityTrustMarks == null) {
+                log.warn("Null trust marks found for entity {}, ignoring it from the result", entity);
+                continue;
+            }
+            for (final TrustMark trustMark : entityTrustMarks) {
+                final String trustMarkType = trustMark.getParsedPayload().getTrustMarkType();
+                if (trustMarkType == null) {
+                    log.warn("Null trust mark type found for entity {}, ignoring it from the result", entity);
+                    continue;
+                }
+                final Instant trustMarkExpiration = trustMark.getParsedPayload().getExpiration();
+                final Instant expiration = trustMarkExpiration == null ? maximumExpiration :
+                    trustMarkExpiration.isBefore(maximumExpiration) ? trustMarkExpiration : maximumExpiration;
+                pairs.add(new Pair<>(trustMarkType, expiration));
+            }
+            result.put(entity, pairs);
+        }
+        return result;
+    }
 }
\ 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