[java-idp-plugin-vci] branch dev/REVISSFLOW updated: Credential configurations, no refresh per request anymore, only timer defaulting to 5min

Codeberg noreply at shibboleth.net
Fri Nov 6 12:37:29 UTC 2026


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

codeberg pushed a commit to branch dev/REVISSFLOW
in repository java-idp-plugin-vci.

View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-vci/commit/08e7806f83ce5780415b74f391da988b68067c7c

The following commit(s) were added to refs/heads/dev/REVISSFLOW by this push:
     new 08e7806  Credential configurations, no refresh per request anymore, only timer defaulting to 5min
08e7806 is described below

commit 08e7806f83ce5780415b74f391da988b68067c7c
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Fri Nov 6 14:36:58 2026 +0200

    Credential configurations, no refresh per request anymore, only timer defaulting to 5min
---
 README.md                                          |  2 +-
 ...FilesystemCredentialIssuerMetadataResolver.java |  3 --
 .../impl/AbstractCredentialValidationAction.java   |  8 +---
 ...owedCredentialConfigurationsLookupFunction.java |  4 --
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  2 +-
 .../plugin/openidvci/conf/openid-vci.properties    |  5 ++-
 ...systemCredentialIssuerMetadataResolverTest.java | 52 ++++++++++++++++++++++
 7 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md
index 979ed4a..dd4f8c1 100644
--- a/README.md
+++ b/README.md
@@ -4965,7 +4965,7 @@ The file comes with the plugin and is loaded automatically.
 |---|---|---|---|
 | `openidvci.credentialConfigurations.resource` | File pathname | `%{idp.home}/metadata/verifiable-credentials.json` | The Credential Configurations. |
 | `openidvci.credentialConfigurations.minRefreshDelay` | Duration | `PT5M` | Lower bound of re-reading the file. |
-| `openidvci.credentialConfigurations.maxRefreshDelay` | Duration | `PT4H` | Upper bound of re-reading the file. |
+| `openidvci.credentialConfigurations.maxRefreshDelay` | Duration | `PT5M` | Upper bound of re-reading the file. A change takes effect within this time. |
 
 #### Metadata documents
 
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolver.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolver.java
index 2c2a255..ec8df37 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolver.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolver.java
@@ -88,9 +88,6 @@ public class DynamicFilesystemCredentialIssuerMetadataResolver extends Filesyste
                 log.debug("{} Starting to resolve value for {}", getLogPrefix(), member);
                 try {
                     final CredentialIssuerMetadataValueResolver resolver = dynamicResolvers.get(member);
-                    if (resolver instanceof RefreshableCredentialIssuerMetadataValueResolver refreshable) {
-                        refreshable.refresh();
-                    }
                     final Object value = resolver.resolveSingle(profileRequestContext);
                     if (value != null) {
                         members.put(member, value);
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/AbstractCredentialValidationAction.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/AbstractCredentialValidationAction.java
index 689cf0b..4852310 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/AbstractCredentialValidationAction.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/AbstractCredentialValidationAction.java
@@ -23,7 +23,6 @@ import javax.annotation.Nonnull;
 import org.geant.shibboleth.plugin.openidvci.credential.CredentialConfiguration;
 import org.geant.shibboleth.plugin.openidvci.credential.CredentialConfigurations;
 import org.geant.shibboleth.plugin.openidvci.credential.resolver.CredentialConfigurationsResolver;
-import org.geant.shibboleth.plugin.openidvci.credential.resolver.RefreshableCredentialConfigurationsResolver;
 import org.geant.shibboleth.plugin.openidvci.profile.OpenIDVCIEventIds;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.context.ProfileRequestContext;
@@ -42,9 +41,7 @@ import net.shibboleth.shared.resolver.ResolverException;
  * {@link CredentialConfigurations} resolved for the request.
  *
  * The configurations come from a resolver shared with every other flow reading
- * them, including the one publishing Credential Issuer metadata. The resolver is
- * refreshed here, so a change to the source still takes effect without a
- * restart, but an unchanged source is not read or parsed again.
+ * them, including the one publishing Credential Issuer metadata.
  */
 abstract class AbstractCredentialValidationAction extends AbstractProfileAction {
 
@@ -92,9 +89,6 @@ abstract class AbstractCredentialValidationAction extends AbstractProfileAction
     protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
         try {
-            if (credentialConfigurationsResolver instanceof RefreshableCredentialConfigurationsResolver refreshable) {
-                refreshable.refresh();
-            }
             credentialConfigurations = credentialConfigurationsResolver.resolveSingle(profileRequestContext);
         } catch (final ResolverException e) {
             log.error("{} Resolving credential configuration failed.", getLogPrefix(), e);
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/logic/AllowedCredentialConfigurationsLookupFunction.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/logic/AllowedCredentialConfigurationsLookupFunction.java
index a5b2afc..3e9fa28 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/logic/AllowedCredentialConfigurationsLookupFunction.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/logic/AllowedCredentialConfigurationsLookupFunction.java
@@ -28,7 +28,6 @@ import javax.annotation.Nullable;
 import org.geant.shibboleth.plugin.openidvci.credential.CredentialConfiguration;
 import org.geant.shibboleth.plugin.openidvci.credential.CredentialConfigurations;
 import org.geant.shibboleth.plugin.openidvci.credential.resolver.CredentialConfigurationsResolver;
-import org.geant.shibboleth.plugin.openidvci.credential.resolver.RefreshableCredentialConfigurationsResolver;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 
@@ -97,9 +96,6 @@ public class AllowedCredentialConfigurationsLookupFunction implements Function<P
 
         final CredentialConfigurations configurations;
         try {
-            if (credentialConfigurationsResolver instanceof RefreshableCredentialConfigurationsResolver refreshable) {
-                refreshable.refresh();
-            }
             configurations = credentialConfigurationsResolver.resolveSingle(profileRequestContext);
         } catch (final ResolverException e) {
             log.error("Resolving Credential Configurations failed, none allowed", e);
diff --git a/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 5ae7ed8..362bbe4 100644
--- a/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/openid-vci-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -154,7 +154,7 @@
         depends-on="shibboleth.LoggingService"
         p:id="openidvci.CredentialConfigurationsResolver"
         p:minRefreshDelay="%{openidvci.credentialConfigurations.minRefreshDelay:PT5M}"
-        p:maxRefreshDelay="%{openidvci.credentialConfigurations.maxRefreshDelay:PT4H}"
+        p:maxRefreshDelay="%{openidvci.credentialConfigurations.maxRefreshDelay:PT5M}"
         c:credentials-ref="openidvci.CredentialsResource" />
 
     <bean id="openidvci.CredentialsResource" class="org.springframework.core.io.FileSystemResource" lazy-init="true"
diff --git a/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties b/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties
index 3c109e6..4a10705 100644
--- a/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties
+++ b/openid-vci-impl/src/main/resources/org/geant/shibboleth/plugin/openidvci/conf/openid-vci.properties
@@ -36,9 +36,10 @@ openidvci.issuer =
 # takes a Status List slot, are stated per credential in that same file, in an
 # '_issuance_configuration' member that is parsed and then dropped from what gets published.
 #openidvci.credentialConfigurations.resource = %{idp.home}/metadata/verifiable-credentials.json
-# Bounds on the next file refresh of the Credential Configurations resource
+# Bounds on the next file refresh of the Credential Configurations resource. A change to the
+# file takes effect at the next refresh, in every flow at once.
 #openidvci.credentialConfigurations.minRefreshDelay = PT5M
-#openidvci.credentialConfigurations.maxRefreshDelay = PT4H
+#openidvci.credentialConfigurations.maxRefreshDelay = PT5M
 
 # Settings for the issuer-metadata flow
 # Flow is available at /openid/vci/issuer-metadata, usually it should be wired from /.well-known/openid-credential-issuer
diff --git a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolverTest.java b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolverTest.java
index 272ab42..2f29f9a 100644
--- a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolverTest.java
+++ b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/metadata/impl/DynamicFilesystemCredentialIssuerMetadataResolverTest.java
@@ -16,6 +16,7 @@
 
 package org.geant.shibboleth.plugin.openidvci.metadata.impl;
 
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -25,6 +26,7 @@ import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
 import org.geant.shibboleth.plugin.openidvci.credential.impl.FilesystemCredentialConfigurationsResolver;
 import org.geant.shibboleth.plugin.openidvci.metadata.CredentialIssuerMetadata;
 import org.geant.shibboleth.plugin.openidvci.metadata.resolver.CredentialIssuerMetadataValueResolver;
+import org.geant.shibboleth.plugin.openidvci.metadata.resolver.RefreshableCredentialIssuerMetadataValueResolver;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.springframework.core.io.ClassPathResource;
 import org.testng.Assert;
@@ -121,6 +123,20 @@ public class DynamicFilesystemCredentialIssuerMetadataResolverTest {
         Assert.assertEquals(metadata.getMembers().get("nonce_endpoint"), "https://overlaid.example.org/nonce");
     }
 
+    @Test
+    public void testResolvingDoesNotRefreshValueResolvers() throws Exception {
+        final CountingValueResolver counting = new CountingValueResolver("https://overlaid.example.org/nonce");
+        final DynamicFilesystemCredentialIssuerMetadataResolver resolver =
+                resolverOf("metadata/openid-credential-issuer.json", Map.of("nonce_endpoint", counting));
+
+        resolver.resolveSingle(null);
+        final CredentialIssuerMetadata metadata = resolver.resolveSingle(null);
+
+        Assert.assertNotNull(metadata);
+        Assert.assertEquals(metadata.getMembers().get("nonce_endpoint"), "https://overlaid.example.org/nonce");
+        Assert.assertEquals(counting.refreshes, 0);
+    }
+
     @Test
     public void testNoCredentialIssuerInFile() {
         Assert.assertThrows(ComponentInitializationException.class,
@@ -208,6 +224,42 @@ public class DynamicFilesystemCredentialIssuerMetadataResolverTest {
                 () -> templatedResolverOf("metadata/openid-credential-issuer-template.json", "not-a-url"));
     }
 
+    /** Refreshable resolver serving a fixed value and counting its refreshes. */
+    private static class CountingValueResolver extends ConstantValueResolver
+            implements RefreshableCredentialIssuerMetadataValueResolver {
+
+        /** Number of refreshes. */
+        private int refreshes;
+
+        /**
+         * Constructor.
+         *
+         * @param constant value to serve
+         */
+        CountingValueResolver(final Object constant) {
+            super(constant);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void refresh() {
+            refreshes++;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public Instant getLastRefresh() {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public Instant getLastUpdate() {
+            return Instant.EPOCH;
+        }
+
+    }
+
     /** Resolver serving a fixed value, standing in for a deployer supplied one. */
     private static class ConstantValueResolver implements CredentialIssuerMetadataValueResolver {
 

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


More information about the commits mailing list