[java-idp-oidc] 02/02: JOIDC-222 - Support for OpenID Federation
Henri Mikkonen
henri.mikkonen at iki.fi
Thu Jan 16 16:08:52 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=78243f10d2ed9b744f3ba69aed8ecca7face6370
commit 78243f10d2ed9b744f3ba69aed8ecca7face6370
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Jan 16 18:08:24 2025 +0200
JOIDC-222 - Support for OpenID Federation
https://shibboleth.atlassian.net/browse/JOIDC-222
Perform trust chain reselection if the selected trust chain does not meet profile configuration
- Rejected trust chains are stored in the trust chain context to avoid reselection
---
.../impl/RelyingPartyTrustChainContext.java | 27 ++++++++++++++-
.../op/oidfed/profile/impl/ResolveTrustChains.java | 2 +-
.../op/oidfed/profile/impl/SelectTrustChain.java | 6 ++++
...eAutomaticRegistrationProfileConfiguration.java | 17 +++++++++-
.../DefaultTrustChainSelectionStrategy.java | 39 ++++++++++++++++++----
.../idp/flows/oidc/authorize/authorize-flow.xml | 1 +
6 files changed, 83 insertions(+), 9 deletions(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyTrustChainContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyTrustChainContext.java
index 94442062..37f0a031 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyTrustChainContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/RelyingPartyTrustChainContext.java
@@ -50,6 +50,9 @@ public final class RelyingPartyTrustChainContext extends BaseContext {
/** Verified trust mark IDs for the selected trust chain. */
@Nullable private Map<String, List<String>> verifiedTrustMarkIds;
+ /** All previously selected but rejected trust chains. */
+ @Nullable private List<List<EntityStatement>> rejectedTrustChains;
+
/**
* Get the resolved trust chains for the relying party.
*
@@ -158,5 +161,27 @@ public final class RelyingPartyTrustChainContext extends BaseContext {
verifiedTrustMarkIds = ids;
return this;
}
-
+
+ /**
+ * Get the previously selected but rejected trust chains for the relying party.
+ *
+ * @return the trust chains
+ */
+ @Nullable public List<List<EntityStatement>> getRejectedTrustChains() {
+ return rejectedTrustChains;
+ }
+
+ /**
+ * Set the previously selected but rejected trust chains for the relying party.
+ *
+ * @param trustChains the trust chains
+ *
+ * @return this context
+ */
+ @Nonnull public RelyingPartyTrustChainContext setRejectedTrustChains(
+ @Nullable final List<List<EntityStatement>> trustChains) {
+ rejectedTrustChains = trustChains;
+ return this;
+ }
+
}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
index e55c5f81..2f5d5d34 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ResolveTrustChains.java
@@ -201,7 +201,7 @@ public class ResolveTrustChains extends AbstractProfileAction {
/** {@inheritDoc} */
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- log.debug("Resolving trust chain for {)", clientId);
+ log.debug("{} Resolving trust chain for {}", getLogPrefix(), clientId);
final List<List<List<EntityStatement>>> cacheResult;
try {
assert clientId != null;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
index 897dfc69..cec81961 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/SelectTrustChain.java
@@ -156,6 +156,12 @@ public class SelectTrustChain extends AbstractProfileAction {
return;
}
+ final List<List<EntityStatement>> rejectedTrustChains = trustChainContext.getRejectedTrustChains();
+ if (rejectedTrustChains != null && rejectedTrustChains.contains(selectedChain.getFirst())) {
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+ log.error("{} The selected trust chain has been previously rejected", getLogPrefix());
+ return;
+ }
trustChainContext.setSelectedTrustChains(selectedChain);
final List<EntityStatement> selectedTrustChain = selectedChain.getFirst();
assert selectedTrustChain != null;
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java
index 24b0f7de..0e4e4ad4 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateAutomaticRegistrationProfileConfiguration.java
@@ -15,6 +15,7 @@
package net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl;
import java.time.Instant;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
@@ -38,6 +39,8 @@ import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.collection.Pair;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -51,11 +54,15 @@ import org.opensaml.profile.action.ActionSupport;
*
* @event {@link EventIds#PROCEED_EVENT_ID}
* @event {@link EventIds#INVALID_MSG_CTX}
+ * @event {@link ValidateAutomaticRegistrationProfileConfiguration#RESELECT_TRUST_CHAIN}
*
* @since 4.3.0
*/
public class ValidateAutomaticRegistrationProfileConfiguration extends AbstractProfileAction {
+ /** ID of event returned if a flow wishes to indicate that another trust chain should be selected instead. */
+ @Nonnull @NotEmpty public static final String RESELECT_TRUST_CHAIN = "ReselectTrustChain";
+
/** Class logger. */
@Nonnull private Logger log = LoggerFactory.getLogger(ValidateAutomaticRegistrationProfileConfiguration.class);
@@ -196,7 +203,15 @@ public class ValidateAutomaticRegistrationProfileConfiguration extends AbstractP
|| !verifiedTrustMarks.get(clientId).containsAll(mandatoryTrustMarks)) {
log.info("{} Rejecting registration as some of the following mandatory trust marks are missing: {}",
getLogPrefix(), mandatoryTrustMarks);
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+ final List<List<EntityStatement>> rejectedTrustChains = trustChainContext.getRejectedTrustChains();
+ if (rejectedTrustChains == null) {
+ trustChainContext.setRejectedTrustChains(List.of(selectedTrustChain.getFirst()));
+ } else {
+ final List<List<EntityStatement>> rejectedChains = new ArrayList<>(rejectedTrustChains);
+ rejectedChains.add(selectedTrustChain.getFirst());
+ trustChainContext.setRejectedTrustChains(CollectionSupport.copyToList(rejectedChains));
+ }
+ ActionSupport.buildEvent(profileRequestContext, RESELECT_TRUST_CHAIN);
return;
}
}
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java
index 702d373d..1e3b84a1 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/navigate/DefaultTrustChainSelectionStrategy.java
@@ -35,7 +35,8 @@ import net.shibboleth.shared.primitive.LoggerFactory;
/**
* Default strategy for choosing a specific trust chain: it simply selects the first one in the list whose size is the
- * shortest.
+ * shortest. The selection must not be included in the list of previously rejected trust chains, obtained via
+ * {@link RelyingPartyTrustChainContext#getRejectedTrustChains()}.
*/
public class DefaultTrustChainSelectionStrategy implements
Function<ProfileRequestContext,Pair<List<EntityStatement>, OIDCClientInformation>> {
@@ -83,18 +84,44 @@ public class DefaultTrustChainSelectionStrategy implements
log.debug("No policy compliant chains located");
return null;
}
-
- int shortestIndex = 0;
+
+ log.trace("Policy-compatible trust chains: {}", policyCompliantChains.size());
if (policyCompliantChains.size() > 1) {
+ int shortestIndex = -1;
for (int i = 0; i < policyCompliantChains.size(); i++) {
final List<EntityStatement> candidate = policyCompliantChains.get(i).getFirst();
- final List<EntityStatement> shortest = policyCompliantChains.get(shortestIndex).getFirst();
- if (candidate != null && shortest != null && candidate.size() < shortest.size()) {
+ if (isTrustChainRejected(trustChainContext, candidate)) {
+ continue;
+ }
+ if (shortestIndex == -1) {
shortestIndex = i;
+ } else {
+ final List<EntityStatement> shortest = policyCompliantChains.get(shortestIndex).getFirst();
+ if (candidate != null && shortest != null && candidate.size() < shortest.size()) {
+ shortestIndex = i;
+ }
}
}
+ log.trace("Shortest non-rejected index {}", shortestIndex);
+ return shortestIndex == -1 ? null : policyCompliantChains.get(shortestIndex);
}
- return policyCompliantChains.get(shortestIndex);
+ final List<EntityStatement> candidate = policyCompliantChains.get(0).getFirst();
+ return isTrustChainRejected(trustChainContext, candidate) ? null : policyCompliantChains.get(0);
}
+ /**
+ * Checks whether the trust chain has been previously rejected in the given context.
+ *
+ * @param trustChainContext context containing the previously rejected trust chain
+ * @param trustChain trust chain to be verified
+ * @return true if trust chain is null or previously rejected, false otherwise
+ */
+ private boolean isTrustChainRejected(@Nonnull final RelyingPartyTrustChainContext trustChainContext,
+ @Nullable final List<EntityStatement> trustChain) {
+ if (trustChain == null) {
+ return true;
+ }
+ final List<List<EntityStatement>> rejectedTrustChains = trustChainContext.getRejectedTrustChains();
+ return rejectedTrustChains != null && rejectedTrustChains.contains(trustChain);
+ }
}
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-flow.xml
index 9846f0f2..5fe04f32 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-flow.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/authorize/authorize-flow.xml
@@ -53,6 +53,7 @@
<evaluate expression="ValidateAutomaticRegistrationProfileConfiguration" />
<evaluate expression="InitializeRelyingPartyContext" />
<evaluate expression="'proceed'" />
+ <transition on="ReselectTrustChain" to="DoAutomaticRegistration" />
<transition on="proceed" to="DoSelectConfiguration">
<set name="flowScope.automaticallyRegistered" value="opensamlProfileRequestContext.ensureInboundMessageContext().containsSubcontext(T(net.shibboleth.oidc.metadata.context.OIDCMetadataContext))" />
</transition>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list