[java-idp-plugin-vci] 01/03: Include issuer if part of definition

Codeberg noreply at shibboleth.net
Tue Apr 28 11:21:54 UTC 2026


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

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

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

commit 7686645f35d890addb419af42945ea53b72329ac
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Tue Apr 28 14:18:55 2026 +0300

    Include issuer if part of definition
---
 .../openidvci/credential/CredentialDefinition.java | 25 +++++++++++++++----
 .../credential/CredentialDefinitionTest.java       |  3 ++-
 .../credentials/CredentialDefinition.json          |  3 ++-
 ...FormJsonLdSelectiveDisclosureJWTCredential.java | 29 +++++++++++++++++++++-
 4 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/openid-vci-api/src/main/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinition.java b/openid-vci-api/src/main/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinition.java
index 96f3c48..e965571 100644
--- a/openid-vci-api/src/main/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinition.java
+++ b/openid-vci-api/src/main/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinition.java
@@ -17,7 +17,6 @@
 package org.geant.shibboleth.plugin.openidvci.credential;
 
 import java.util.List;
-import java.util.Map;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -29,7 +28,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonInclude.Include;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.oauth2.sdk.ParseException;
 
 /**
  * Credential definition in {@link CredentialConfiguration} as defined in
@@ -59,6 +57,20 @@ public class CredentialDefinition {
     @JsonProperty("type")
     private final List<String> type;
 
+    /** Issuer in credential definition. */
+    @Nullable
+    @JsonProperty("issuer")
+    @JsonInclude(Include.NON_NULL)
+    private final String issuer;
+
+    /**
+     * 
+     * @return
+     */
+    public String getIssuer() {
+        return issuer;
+    }
+
     /**
      * Constructor.
      * 
@@ -67,12 +79,14 @@ public class CredentialDefinition {
      * @param type    Type of credential definition
      */
     private CredentialDefinition(@JsonProperty("@context") @Nonnull List<String> context,
-            @JsonProperty("id") @Nullable String id, @JsonProperty("type") @Nonnull List<String> type) {
+            @JsonProperty("id") @Nullable String id, @JsonProperty("type") @Nonnull List<String> type,
+            @JsonProperty("issuer") @Nullable String issuer) {
         assert context != null;
         assert type != null;
         this.context = context;
         this.type = type;
         this.id = id;
+        this.issuer = issuer;
     }
 
     /**
@@ -129,10 +143,11 @@ public class CredentialDefinition {
 
     @JsonCreator
     public static CredentialDefinition of(@JsonProperty("@context") @Nullable List<String> context,
-            @JsonProperty("id") @Nullable String id, @JsonProperty("type") @Nullable List<String> type) {
+            @JsonProperty("id") @Nullable String id, @JsonProperty("type") @Nullable List<String> type,
+            @JsonProperty("issuer") @Nullable String issuer) {
         if (context == null || type == null) {
             return null;
         }
-        return new CredentialDefinition(context, id, type);
+        return new CredentialDefinition(context, id, type, issuer);
     }
 }
diff --git a/openid-vci-api/src/test/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinitionTest.java b/openid-vci-api/src/test/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinitionTest.java
index ce9f2b3..7acdc46 100644
--- a/openid-vci-api/src/test/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinitionTest.java
+++ b/openid-vci-api/src/test/java/org/geant/shibboleth/plugin/openidvci/credential/CredentialDefinitionTest.java
@@ -49,8 +49,9 @@ public class CredentialDefinitionTest {
         Assert.assertEquals(credentialDefinition.getType().get(0), "VerifiableCredential");
         Assert.assertEquals(credentialDefinition.getType().get(1), "UniversityDegreeCredential");
         Assert.assertEquals(credentialDefinition.getId(), "http://university.example/credentials/3732");
+        Assert.assertEquals(credentialDefinition.getIssuer(), "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IlREaW5WM3R5b2VUNEVmVU1Bd25QZnlkbkdzay1qVnczQlFXNldGdnZjRk0iLCJ5IjoiMGplbkx3UG9IbzRfM21Ma2gyMXV5Y0hWTzM3d2hCUTZqd3pDLV9VUXBsdyIsInVzZSI6InNpZyIsImFsZyI6IkVTMjU2In0");
         Assert.assertEquals(credentialDefinition.serialize(),
-                "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://www.w3.org/2018/credentials/examples/v1\"],\"id\":\"http://university.example/credentials/3732\",\"type\":[\"VerifiableCredential\",\"UniversityDegreeCredential\"]}");
+                "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://www.w3.org/2018/credentials/examples/v1\"],\"id\":\"http://university.example/credentials/3732\",\"type\":[\"VerifiableCredential\",\"UniversityDegreeCredential\"],\"issuer\":\"did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IlREaW5WM3R5b2VUNEVmVU1Bd25QZnlkbkdzay1qVnczQlFXNldGdnZjRk0iLCJ5IjoiMGplbkx3UG9IbzRfM21Ma2gyMXV5Y0hWTzM3d2hCUTZqd3pDLV9VUXBsdyIsInVzZSI6InNpZyIsImFsZyI6IkVTMjU2In0\"}");
 
     }
 
diff --git a/openid-vci-api/src/test/resources/credentials/CredentialDefinition.json b/openid-vci-api/src/test/resources/credentials/CredentialDefinition.json
index 5b646e9..fb41c00 100644
--- a/openid-vci-api/src/test/resources/credentials/CredentialDefinition.json
+++ b/openid-vci-api/src/test/resources/credentials/CredentialDefinition.json
@@ -7,5 +7,6 @@
 	"type": [
 		"VerifiableCredential",
 		"UniversityDegreeCredential"
-	]
+	],
+	"issuer": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IlREaW5WM3R5b2VUNEVmVU1Bd25QZnlkbkdzay1qVnczQlFXNldGdnZjRk0iLCJ5IjoiMGplbkx3UG9IbzRfM21Ma2gyMXV5Y0hWTzM3d2hCUTZqd3pDLV9VUXBsdyIsInVzZSI6InNpZyIsImFsZyI6IkVTMjU2In0"
 }
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormJsonLdSelectiveDisclosureJWTCredential.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormJsonLdSelectiveDisclosureJWTCredential.java
index f911795..692b895 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormJsonLdSelectiveDisclosureJWTCredential.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormJsonLdSelectiveDisclosureJWTCredential.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 
@@ -35,7 +36,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import net.shibboleth.idp.profile.AbstractProfileAction;
+import net.shibboleth.profile.context.navigate.IssuerLookupFunction;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.logic.Constraint;
 
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.oauth2.sdk.ParseException;
@@ -68,6 +71,27 @@ public class FormJsonLdSelectiveDisclosureJWTCredential extends AbstractProfileA
     @NonnullBeforeExec
     private CredentialOfferRequestedCredential credential;
 
+    /** Strategy used to obtain the response issuer value. */
+    @Nonnull
+    private Function<ProfileRequestContext, String> issuerLookupStrategy;
+
+    /**
+     * Constructor.
+     */
+    public FormJsonLdSelectiveDisclosureJWTCredential() {
+        issuerLookupStrategy = (Function<ProfileRequestContext, String>) new IssuerLookupFunction();
+    }
+
+    /**
+     * Set the strategy used to locate the issuer value to use.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setIssuerLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
+        checkSetterPreconditions();
+        issuerLookupStrategy = Constraint.isNotNull(strategy, "IssuerLookupStrategy lookup strategy cannot be null");
+    }
+
     @Override
     protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
 
@@ -127,11 +151,14 @@ public class FormJsonLdSelectiveDisclosureJWTCredential extends AbstractProfileA
         List<JWTClaimsSet> credentials = new ArrayList<>();
         ctx.getCredentialShells().forEach(cred -> {
             try {
+                String issuer = ctx.getCredentialConfiguration().getCredentialDefinition().getIssuer();
+                issuer = issuer == null ? issuerLookupStrategy.apply(profileRequestContext) : issuer;
                 credentials.add(new JWTClaimsSet.Builder(cred.toJWTClaimsSet())
                         .claim("@context", ctx.getCredentialConfiguration().getCredentialDefinition().getContext())
                         .claim("id", ctx.getCredentialConfiguration().getCredentialDefinition().getId())
                         .claim("type", ctx.getCredentialConfiguration().getCredentialDefinition().getType())
-                        .claim("credentialSubject", credentialSubject).claim("_sd_alg", "sha-256").build());
+                        .claim("issuer", issuer).claim("credentialSubject", credentialSubject)
+                        .claim("_sd_alg", "sha-256").build());
             } catch (ParseException e) {
                 log.error("{} Parsing credential failed", getLogPrefix(), e);
                 ActionSupport.buildEvent(profileRequestContext, OpenIDVCIEventIds.INVALID_CREDENTIAL);

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


More information about the commits mailing list