[java-oidfed-common] branch main updated: Move signed-keyset actions from the OP plugin
Codeberg
noreply at shibboleth.net
Thu Jun 4 11:33:55 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/837a0ab737eb5d924645fed17712544bffb3f22c
The following commit(s) were added to refs/heads/main by this push:
new 837a0ab Move signed-keyset actions from the OP plugin
837a0ab is described below
commit 837a0ab737eb5d924645fed17712544bffb3f22c
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Jun 4 14:32:34 2026 +0300
Move signed-keyset actions from the OP plugin
---
.../oidfed/profile/impl/BuildSignedKeyset.java | 142 ++++++++++++++
.../impl/FormOutboundSignedKeysetResponse.java | 216 +++++++++++++++++++++
.../InitializeEntityStatementContextForKeyset.java | 190 ++++++++++++++++++
3 files changed, 548 insertions(+)
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/BuildSignedKeyset.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/BuildSignedKeyset.java
new file mode 100644
index 0000000..a253e54
--- /dev/null
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/BuildSignedKeyset.java
@@ -0,0 +1,142 @@
+/*
+ * 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.oidfed.profile.impl;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Date;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import com.nimbusds.jose.jwk.JWKSet;
+import com.nimbusds.jwt.JWTClaimsSet;
+
+import net.shibboleth.idp.profile.IdPEventIds;
+import net.shibboleth.oidfed.profile.config.navigate.EntityStatementLifetimeLookupFunction;
+import net.shibboleth.oidfed.profile.config.navigate.OptionalClaimsLookupStrategiesLookupFunction;
+import net.shibboleth.oidfed.profile.impl.AbstractBuildEntityStatementAction;
+import net.shibboleth.oidfed.profile.impl.EntityStatementContext;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+import org.opensaml.profile.action.ActionSupport;
+
+/**
+ * Action that creates a keyset JWT, and stores it to an {@link EntityStatementContext}.
+ *
+ * @event {@link EventIds#PROCEED_EVENT_ID}
+ * @event {@link EventIds#INVALID_PROFILE_CTX}
+ * @event {@link EventIds#IO_ERROR}
+ * @event {@link IdPEventIds#INVALID_PROFILE_CONFIG}
+ */
+public class BuildSignedKeyset extends AbstractBuildEntityStatementAction {
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(BuildSignedKeyset.class);
+
+ /** Strategy used to obtain the entity statement lifetime. */
+ @Nonnull private Function<ProfileRequestContext,Duration> entityStatementLifetimeLookupStrategy;
+
+ /** Strategy used to locate strategies for optional claims. */
+ @Nonnull private Function<ProfileRequestContext,Map<String, Function<ProfileRequestContext,Object>>>
+ optionalClaimsLookupStrategiesLookupStrategy;
+
+ /** Constructor. */
+ public BuildSignedKeyset() {
+ entityStatementLifetimeLookupStrategy = new EntityStatementLifetimeLookupFunction();
+ optionalClaimsLookupStrategiesLookupStrategy = new OptionalClaimsLookupStrategiesLookupFunction();
+ }
+
+ /**
+ * Set the strategy used to obtain the entity statement lifetime.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setEntityStatementLifetimeLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,Duration> strategy) {
+ checkSetterPreconditions();
+
+ entityStatementLifetimeLookupStrategy =
+ Constraint.isNotNull(strategy, "Entity statement lifetime lookup strategy cannot be null");
+ }
+
+ /**
+ * Set the strategy used to locate strategies for optional claims.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setOptionalClaimsLookupStrategiesLookupStrategy(@Nonnull final
+ Function<ProfileRequestContext, Map<String,Function<ProfileRequestContext,Object>>> strategy) {
+ checkSetterPreconditions();
+
+ optionalClaimsLookupStrategiesLookupStrategy =
+ Constraint.isNotNull(strategy, "Optional claims lookup strategies lookup strategy cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean populateClaimsSetBuilder(@Nonnull final JWTClaimsSet.Builder builder,
+ @Nonnull final ProfileRequestContext profileRequestContext) {
+
+ final Duration lifetime = entityStatementLifetimeLookupStrategy.apply(profileRequestContext);
+ if (lifetime == null || Duration.ZERO.equals(lifetime)) {
+ log.debug("{} No lifetime supplied for entity statement", getLogPrefix());
+ } else {
+ final Instant now = Instant.now();
+ final Instant dateExp = now.plus(lifetime);
+ assert dateExp != null;
+
+ log.debug("{} Set expiration time of entity statement into {}", getLogPrefix(), dateExp);
+ builder.expirationTime(Date.from(dateExp));
+ }
+
+ final JWKSet jwks = entityStatementCtx.getKeys();
+ if (jwks == null || jwks.isEmpty()) {
+ log.error("{} No credentials to publish resolved for signed keyset entity statement", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
+ return false;
+
+ }
+
+ log.trace("{} Resolved jwks to publish: {}", getLogPrefix(), jwks);
+
+ builder.claim("keys", jwks.toJSONObject(true).get("keys"));
+
+ final Map<String, Function<ProfileRequestContext, Object>> optionalClaimsLookupStrategies =
+ optionalClaimsLookupStrategiesLookupStrategy.apply(profileRequestContext);
+ if (optionalClaimsLookupStrategies != null) {
+ for (final String claim : optionalClaimsLookupStrategies.keySet()) {
+ log.trace("{} Looking up the value for clain {}", getLogPrefix(), claim);
+ final Function<ProfileRequestContext,Object> lookup = optionalClaimsLookupStrategies.get(claim);
+ final Object value = lookup.apply(profileRequestContext);
+ if (value != null) {
+ log.debug("{} Resolved value {} for clain {}", getLogPrefix(), value, claim);
+ builder.claim(claim, value);
+ } else {
+ log.debug("{} No value resolved for clain {}", getLogPrefix(), claim);
+ }
+ }
+ }
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/FormOutboundSignedKeysetResponse.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/FormOutboundSignedKeysetResponse.java
new file mode 100644
index 0000000..d1fb3b6
--- /dev/null
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/FormOutboundSignedKeysetResponse.java
@@ -0,0 +1,216 @@
+/*
+ * 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.oidfed.profile.impl;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
+import org.slf4j.Logger;
+
+import com.nimbusds.jwt.SignedJWT;
+import com.nimbusds.oauth2.sdk.Response;
+
+import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.oidc.metadata.cache.MetadataCache;
+import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
+import net.shibboleth.oidfed.messaging.impl.SignedKeysetResponse;
+import net.shibboleth.oidfed.metadata.cache.ResponseContainerExpirationCriterion;
+import net.shibboleth.oidfed.metadata.cache.local.NimbusResponseContainer;
+import net.shibboleth.oidfed.metadata.cache.local.NimbusResponseCriterion;
+import net.shibboleth.oidfed.profile.config.navigate.CachedSuccessResponseLifetimeLookupFunction;
+import net.shibboleth.oidfed.profile.impl.EntityStatementContext;
+import net.shibboleth.oidfed.profile.impl.RelyingPartyCachedMessageContext;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
+
+/**
+ * This action builds a response for the OpenID federation configuration request. The response contains an
+ * {@link SignedJWT} obtained from {@link EntityStatementContext#getJWT()}.
+ */
+public class FormOutboundSignedKeysetResponse extends AbstractProfileAction {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(FormOutboundSignedKeysetResponse.class);
+
+ /** Metadata cache for cached response containers. */
+ @NonnullAfterInit private MetadataCache<NimbusResponseContainer> responseCache;
+
+ /** Strategy used to locate the cached message context. */
+ @Nonnull
+ private Function<ProfileRequestContext, RelyingPartyCachedMessageContext> cachedMessageContextLookupStrategy;
+
+ /** Strategy used to locate the subcontext to hold the statement. */
+ @Nonnull private Function<ProfileRequestContext,EntityStatementContext> entityStatementContextLookupStrategy;
+
+ /** Strategy used to locate the lifetime for the cached response record. */
+ @Nonnull private Function<ProfileRequestContext,Duration> cachedResponseLifetimeLookupStrategy;
+
+ /** JWT used to build entity statement. */
+ @Nullable private SignedJWT jwt;
+
+ /** The resolve entity context to operate on. */
+ @NonnullBeforeExec private RelyingPartyCachedMessageContext cachedMessageContext;
+
+ /**
+ * Constructor.
+ */
+ public FormOutboundSignedKeysetResponse() {
+ final Function<ProfileRequestContext,EntityStatementContext> escls =
+ new ChildContextLookup<>(EntityStatementContext.class).compose(
+ new OutboundMessageContextLookup());
+ assert escls != null;
+ entityStatementContextLookupStrategy = escls;
+ cachedMessageContextLookupStrategy = new ChildContextLookup<>(RelyingPartyCachedMessageContext.class);
+ cachedResponseLifetimeLookupStrategy = new CachedSuccessResponseLifetimeLookupFunction();
+ }
+
+ /**
+ * Set the strategy used to locate the subcontext to hold the statement
+ *
+ * @param strategy What to set.
+ */
+ public void setEntityStatementContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,EntityStatementContext> strategy) {
+ checkSetterPreconditions();
+ entityStatementContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
+ }
+
+ /**
+ * Set the strategy used to locate the cached message context
+ *
+ * @param strategy What to set.
+ */
+ public void setCachedMessageContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,RelyingPartyCachedMessageContext> strategy) {
+ checkSetterPreconditions();
+ cachedMessageContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null!");
+ }
+
+ /**
+ * Set the metadata cache for cached response containers.
+ *
+ * @param cache What to set.
+ */
+ public void setResponseCache(@Nonnull final MetadataCache<NimbusResponseContainer> cache) {
+ checkSetterPreconditions();
+ responseCache = Constraint.isNotNull(cache, "Response metadata cache cannot be null");
+ }
+
+ /**
+ * Set the strategy used to locate the lifetime for the cached response record.
+ *
+ * @param strategy What to set.
+ */
+ public void setCachedResponseLifetimeLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, Duration> strategy) {
+ checkSetterPreconditions();
+ cachedResponseLifetimeLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (responseCache == null) {
+ throw new ComponentInitializationException("Response metadata cache cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+
+ if (!super.doPreExecute(profileRequestContext)) {
+ return false;
+ }
+ cachedMessageContext = cachedMessageContextLookupStrategy.apply(profileRequestContext);
+ if (cachedMessageContext == null) {
+ log.error("{} Could not resolve cached message context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return false;
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ final Response cachedResponse = cachedMessageContext.getCachedResponse();
+ if (cachedResponse != null) {
+ log.debug("{} Cached response found, storing in to the outbound message context", getLogPrefix());
+ profileRequestContext.ensureOutboundMessageContext().setMessage(cachedResponse);
+ return;
+ }
+ log.debug("{} No cached response found, resolving the response JWT from the context", getLogPrefix());
+ final EntityStatementContext entityStatementContext =
+ entityStatementContextLookupStrategy.apply(profileRequestContext);
+ if (entityStatementContext == null) {
+ log.error("{} Could not resolve entity statement context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return;
+ }
+ if (entityStatementContext.getJWT() instanceof SignedJWT signedJwt) {
+ jwt = signedJwt;
+ } else {
+ log.error("{} No signed JWT found from the entity statement context", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return;
+ }
+
+ assert jwt != null;
+ final SignedKeysetResponse response = new SignedKeysetResponse(jwt);
+ final NimbusResponseCriterion responseCriterion = new NimbusResponseCriterion(response);
+ final Duration lifetime = cachedResponseLifetimeLookupStrategy.apply(profileRequestContext);
+ if (lifetime == null) {
+ log.error("{} Could not resolve lifetime for the cached response record", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return;
+ }
+ final Instant expiration = Instant.now().plus(lifetime);
+ assert expiration != null;
+ final ResponseContainerExpirationCriterion expirationCriterion =
+ new ResponseContainerExpirationCriterion(expiration);
+ final CriteriaSet criteria = new CriteriaSet(responseCriterion, expirationCriterion);
+ try {
+ final List<NimbusResponseContainer> result = responseCache.get(criteria);
+ if (result.size() != 1) {
+ log.error("{} Unexpected result (size={}) when storing response record into the metadata cache",
+ getLogPrefix(), result.size());
+ } else {
+ log.debug("{} Response stored into the cache", getLogPrefix());
+ }
+ } catch (final MetadataCacheException e) {
+ log.error("{} Could not store the response record into tht metadata cache", getLogPrefix(), e);
+ }
+
+ profileRequestContext.ensureOutboundMessageContext().setMessage(response);
+ }
+}
\ No newline at end of file
diff --git a/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/InitializeEntityStatementContextForKeyset.java b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/InitializeEntityStatementContextForKeyset.java
new file mode 100644
index 0000000..48e8957
--- /dev/null
+++ b/oidfed-common-impl/src/main/java/net/shibboleth/oidfed/profile/impl/InitializeEntityStatementContextForKeyset.java
@@ -0,0 +1,190 @@
+/*
+ * 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.oidfed.profile.impl;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
+import org.opensaml.security.config.SecurityConfiguration;
+import org.opensaml.security.credential.Credential;
+import org.slf4j.Logger;
+
+import com.nimbusds.jose.jwk.JWKSet;
+
+import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.idp.profile.IdPEventIds;
+import net.shibboleth.oidc.profile.config.JSONSecurityConfiguration;
+import net.shibboleth.oidc.security.CredentialConversionUtil;
+import net.shibboleth.oidfed.profile.impl.EntityStatementContext;
+import net.shibboleth.profile.config.ProfileConfiguration;
+import net.shibboleth.profile.context.RelyingPartyContext;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.action.ActionSupport;
+
+/**
+ * Action that creates and initializes the {@link EntityStatementContext}.
+ *
+ * @event {@link EventIds#PROCEED_EVENT_ID}
+ * @event {@link EventIds#INVALID_PROFILE_CTX}
+ * @event {@link EventIds#IO_ERROR}
+ */
+public class InitializeEntityStatementContextForKeyset extends AbstractProfileAction {
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(InitializeEntityStatementContextForKeyset.class);
+
+ /** Strategy used to create the subcontext to hold the statement. */
+ @Nonnull private Function<ProfileRequestContext,EntityStatementContext> entityStatementContextCreationStrategy;
+
+ /**
+ * Strategy used to locate the {@link RelyingPartyContext} associated with a given {@link ProfileRequestContext}.
+ */
+ @Nonnull private Function<ProfileRequestContext, RelyingPartyContext> relyingPartyContextLookupStrategy;
+
+ /**
+ * Strategy used to locate the list of credentials to publish.
+ */
+ @Nonnull private Function<JSONSecurityConfiguration, List<Credential>> credentialsToPublishLookupStrategy;
+
+ /** Security configuration we look for keys to publish. */
+ @Nullable private JSONSecurityConfiguration secConfiguration;
+
+ /** Entity statement context. */
+ @NonnullBeforeExec private EntityStatementContext entityStatementCtx;
+
+ /** Constructor. */
+ public InitializeEntityStatementContextForKeyset() {
+ final Function<ProfileRequestContext,EntityStatementContext> esccs =
+ new ChildContextLookup<>(EntityStatementContext.class, true).compose(
+ new OutboundMessageContextLookup());
+ assert esccs != null;
+ entityStatementContextCreationStrategy = esccs;
+ relyingPartyContextLookupStrategy = new ChildContextLookup<>(RelyingPartyContext.class);
+ credentialsToPublishLookupStrategy = secConfig -> Collections.emptyList();
+ }
+
+ /**
+ * Set the strategy used to create the {@link EntityStatementContext} to use.
+ *
+ * @param strategy creation strategy
+ */
+ public void setEntityStatementContextCreationStrategy(
+ @Nonnull final Function<ProfileRequestContext,EntityStatementContext> strategy) {
+ checkSetterPreconditions();
+
+ entityStatementContextCreationStrategy =
+ Constraint.isNotNull(strategy, "EntityStatementContext creation strategy cannot be null");
+ }
+
+ /**
+ * Set the strategy used to locate the {@link RelyingPartyContext} associated with a given
+ * {@link ProfileRequestContext}.
+ *
+ * @param strategy strategy used to locate the {@link RelyingPartyContext} associated with a given
+ * {@link ProfileRequestContext}
+ */
+ public void setRelyingPartyContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, RelyingPartyContext> strategy) {
+ checkSetterPreconditions();
+
+ relyingPartyContextLookupStrategy =
+ Constraint.isNotNull(strategy, "RelyingPartyContext lookup strategy cannot be null");
+ }
+
+ /**
+ * Set the strategy used to locate the credentials to publish at the KeySet endpoint.
+ *
+ * @param strategy the strategy.
+ */
+ public void setCredentialsToPublishLookupStrategy(
+ @Nonnull final Function<JSONSecurityConfiguration, List<Credential>> strategy) {
+ checkSetterPreconditions();
+
+ credentialsToPublishLookupStrategy = Constraint.isNotNull(strategy,
+ "credentialsToPublishLookupStrategy can not be null");
+ }
+
+ // Checkstyle: CyclomaticComplexity|MethodLength OFF
+ /** {@inheritDoc} */
+ @Override
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ if (!super.doPreExecute(profileRequestContext)) {
+ return false;
+ }
+
+ entityStatementCtx = entityStatementContextCreationStrategy.apply(profileRequestContext);
+ if (entityStatementCtx == null) {
+ log.error("{} Unable to create EntityStatementContext", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return false;
+ }
+
+ final RelyingPartyContext rpCtx = relyingPartyContextLookupStrategy.apply(profileRequestContext);
+ if (rpCtx == null) {
+ log.debug("{} No relying party context associated with this profile request", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_RELYING_PARTY_CTX);
+ return false;
+ }
+
+ final ProfileConfiguration profileConfig = rpCtx.getProfileConfig();
+ if (profileConfig == null) {
+ log.debug("{} No profile configuration associated with this profile request", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_RELYING_PARTY_CTX);
+ return false;
+ }
+
+ final SecurityConfiguration securityConfig =
+ profileConfig.getSecurityConfiguration(profileRequestContext);
+
+ if (!(securityConfig instanceof JSONSecurityConfiguration)) {
+ log.debug("{} No security configuration associated with the profile configuration of the profile request",
+ getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
+ return false;
+ }
+
+ secConfiguration = (JSONSecurityConfiguration) securityConfig;
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+
+ final List<Credential> credentialsToPublish = credentialsToPublishLookupStrategy.apply(secConfiguration);
+ if (credentialsToPublish == null || credentialsToPublish.isEmpty()) {
+ log.error("{} No credentials to publish resolved for signed keyset entity statement", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, IdPEventIds.INVALID_PROFILE_CONFIG);
+ return;
+ }
+
+ final JWKSet jwks = new JWKSet(credentialsToPublish.stream()
+ .map(credential -> CredentialConversionUtil.credentialToKey(credential))
+ .toList());
+ log.trace("{} Resolved jwks to set in the contet: {}", getLogPrefix(), jwks);
+ entityStatementCtx.setKeys(jwks);
+ }
+}
\ 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