[java-idp-plugin-vci] 02/02: JSONSuccessResponse for the unsigned document. Vary set by the action. Warn when signed metadata has no certificate chain
Codeberg
noreply at shibboleth.net
Fri Nov 6 12:16: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/3c161d972512ce612fa1dc35d8ee5c098dee5c5e
commit 3c161d972512ce612fa1dc35d8ee5c098dee5c5e
Author: Janne Lauros <janne.lauros at csc.fi>
AuthorDate: Fri Nov 6 14:15:52 2026 +0200
JSONSuccessResponse for the unsigned document. Vary set by the action. Warn when signed metadata has no certificate chain
---
.../CredentialIssuerMetadataSuccessResponse.java | 78 ----------------------
...nedCredentialIssuerMetadataSuccessResponse.java | 1 -
.../FormOutboundIssuerMetadataResponseMessage.java | 18 ++---
...mOutboundIssuerMetadataResponseMessageTest.java | 18 +++--
4 files changed, 14 insertions(+), 101 deletions(-)
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/CredentialIssuerMetadataSuccessResponse.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/CredentialIssuerMetadataSuccessResponse.java
deleted file mode 100644
index dbbe649..0000000
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/CredentialIssuerMetadataSuccessResponse.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2025, GÉANT
- *
- * 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 org.geant.shibboleth.plugin.openidvci.messaging.impl;
-
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.common.contenttype.ContentType;
-import com.nimbusds.oauth2.sdk.SuccessResponse;
-import com.nimbusds.oauth2.sdk.http.HTTPResponse;
-
-/**
- * Response carrying the Credential Issuer metadata, as in <a href=
- * "https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-credential-issuer-metadata">
- * OpenID4VCI</a>.
- */
-public class CredentialIssuerMetadataSuccessResponse implements SuccessResponse {
-
- /** Serialized metadata document. */
- @Nonnull
- private final String content;
-
- /**
- * Constructor.
- *
- * @param metadata members of the metadata document
- *
- * @throws JsonProcessingException if the members cannot be serialized
- */
- public CredentialIssuerMetadataSuccessResponse(@Nonnull final Map<String, Object> metadata)
- throws JsonProcessingException {
- content = new ObjectMapper().writeValueAsString(metadata);
- }
-
- /**
- * Get the serialized metadata document.
- *
- * @return serialized metadata document
- */
- @Nonnull
- public String getContent() {
- return content;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean indicatesSuccess() {
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- public HTTPResponse toHTTPResponse() {
- final HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK);
- httpResponse.setEntityContentType(ContentType.APPLICATION_JSON);
- httpResponse.setHeader("Vary", "Accept");
- httpResponse.setContent(content);
- return httpResponse;
- }
-
-}
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/SignedCredentialIssuerMetadataSuccessResponse.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/SignedCredentialIssuerMetadataSuccessResponse.java
index a893e0c..4c369b7 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/SignedCredentialIssuerMetadataSuccessResponse.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/messaging/impl/SignedCredentialIssuerMetadataSuccessResponse.java
@@ -65,7 +65,6 @@ public class SignedCredentialIssuerMetadataSuccessResponse implements SuccessRes
public HTTPResponse toHTTPResponse() {
final HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK);
httpResponse.setEntityContentType(ContentType.APPLICATION_JWT);
- httpResponse.setHeader("Vary", "Accept");
httpResponse.setContent(content);
return httpResponse;
}
diff --git a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessage.java b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessage.java
index 6c248a4..e82ae9b 100644
--- a/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessage.java
+++ b/openid-vci-impl/src/main/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessage.java
@@ -24,7 +24,6 @@ import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.geant.shibboleth.plugin.openidvci.messaging.impl.CredentialIssuerMetadataSuccessResponse;
import org.geant.shibboleth.plugin.openidvci.messaging.impl.SignedCredentialIssuerMetadataSuccessResponse;
import org.geant.shibboleth.plugin.openidvci.metadata.CredentialIssuerMetadata;
import org.geant.shibboleth.plugin.openidvci.security.impl.CertificateChainJWSTokenSigner;
@@ -36,15 +35,16 @@ import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
import org.slf4j.Logger;
-import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.net.HttpHeaders;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import net.minidev.json.JSONObject;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.idp.profile.IdPEventIds;
+import net.shibboleth.oidc.profile.messaging.JSONSuccessResponse;
import net.shibboleth.oidc.security.jose.SignatureException;
import net.shibboleth.oidc.security.jose.SignatureSigningParameters;
import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
@@ -57,7 +57,7 @@ import net.shibboleth.shared.primitive.StringSupport;
import net.shibboleth.shared.resolver.ResolverException;
/**
- * Action forming {@link CredentialIssuerMetadataSuccessResponse}, or
+ * Action forming {@link JSONSuccessResponse}, or
* {@link SignedCredentialIssuerMetadataSuccessResponse} when the request names
* signed metadata and signing is configured, from the document the attached
* {@link CredentialIssuerMetadataResolver} resolves.
@@ -217,16 +217,9 @@ public class FormOutboundIssuerMetadataResponseMessage extends AbstractProfileAc
+ "publishing the document unsigned", getLogPrefix());
}
- final CredentialIssuerMetadataSuccessResponse unsigned;
- try {
- unsigned = new CredentialIssuerMetadataSuccessResponse(metadata.getMembers());
- } catch (final JsonProcessingException e) {
- log.error("{} Could not serialize Credential Issuer metadata", getLogPrefix(), e);
- ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
- return;
- }
setHeaders(response);
- profileRequestContext.ensureOutboundMessageContext().setMessage(unsigned);
+ profileRequestContext.ensureOutboundMessageContext()
+ .setMessage(new JSONSuccessResponse(new JSONObject(metadata.getMembers())));
log.debug("{} Publishing Credential Issuer metadata of {}, members {}", getLogPrefix(),
metadata.getCredentialIssuer(), metadata.getMembers().keySet());
@@ -282,6 +275,7 @@ public class FormOutboundIssuerMetadataResponseMessage extends AbstractProfileAc
* @param response response to set the headers of
*/
private void setHeaders(@Nonnull final HttpServletResponse response) {
+ response.setHeader(HttpHeaders.VARY, HttpHeaders.ACCEPT);
response.setHeader(HttpHeaders.CACHE_CONTROL, cacheControl);
response.setHeader(HttpHeaders.X_CONTENT_TYPE_OPTIONS, FormOutboundMetadataDocumentResponseMessage.NOSNIFF);
response.setHeader(HttpHeaders.CONTENT_SECURITY_POLICY,
diff --git a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessageTest.java b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessageTest.java
index 86e3365..ca2c57a 100644
--- a/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessageTest.java
+++ b/openid-vci-impl/src/test/java/org/geant/shibboleth/plugin/openidvci/profile/impl/FormOutboundIssuerMetadataResponseMessageTest.java
@@ -29,7 +29,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import org.geant.shibboleth.plugin.openidvci.messaging.impl.CredentialIssuerMetadataSuccessResponse;
import org.geant.shibboleth.plugin.openidvci.messaging.impl.SignedCredentialIssuerMetadataSuccessResponse;
import org.geant.shibboleth.plugin.openidvci.metadata.CredentialIssuerMetadata;
import org.geant.shibboleth.plugin.openidvci.metadata.resolver.CredentialIssuerMetadataResolver;
@@ -60,6 +59,7 @@ import net.shibboleth.idp.profile.IdPEventIds;
import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
import net.shibboleth.idp.profile.testing.ActionTestingSupport;
import net.shibboleth.idp.profile.testing.RequestContextBuilder;
+import net.shibboleth.oidc.profile.messaging.JSONSuccessResponse;
import net.shibboleth.oidc.jwa.support.SignatureConstants;
import net.shibboleth.oidc.security.credential.BasicJWKCredential;
import net.shibboleth.oidc.security.jose.SignatureSigningParameters;
@@ -139,6 +139,7 @@ public class FormOutboundIssuerMetadataResponseMessageTest {
}
private void assertDocumentHeaders(final String cacheControl) {
+ Assert.assertEquals(httpResponse.getHeaders("Vary"), List.of("Accept"));
Assert.assertEquals(httpResponse.getHeaders("Cache-Control"), List.of(cacheControl));
Assert.assertEquals(httpResponse.getHeaders("X-Content-Type-Options"),
List.of(FormOutboundMetadataDocumentResponseMessage.NOSNIFF));
@@ -192,10 +193,10 @@ public class FormOutboundIssuerMetadataResponseMessageTest {
ActionTestingSupport.assertProceedEvent(action.execute(requestCtx));
final Object message = profileRequestCtx.ensureOutboundMessageContext().getMessage();
- Assert.assertTrue(message instanceof CredentialIssuerMetadataSuccessResponse);
+ Assert.assertTrue(message instanceof JSONSuccessResponse);
final Map<String, Object> published = new ObjectMapper().readValue(
- ((CredentialIssuerMetadataSuccessResponse) message).toHTTPResponse().getContent(),
+ ((JSONSuccessResponse) message).toHTTPResponse().getContent(),
new TypeReference<LinkedHashMap<String, Object>>() {
});
Assert.assertEquals(published.keySet(), members().keySet());
@@ -240,10 +241,7 @@ public class FormOutboundIssuerMetadataResponseMessageTest {
ActionTestingSupport.assertProceedEvent(action.execute(requestCtx));
- final Object message = profileRequestCtx.ensureOutboundMessageContext().getMessage();
- Assert.assertEquals(
- ((CredentialIssuerMetadataSuccessResponse) message).toHTTPResponse().getHeaderMap().get("Vary"),
- List.of("Accept"));
+ Assert.assertEquals(httpResponse.getHeaders("Vary"), List.of("Accept"));
}
@Test(dataProvider = "unsignedAccept")
@@ -257,7 +255,7 @@ public class FormOutboundIssuerMetadataResponseMessageTest {
actionOf(CredentialIssuerMetadata.parse(members())).execute(requestCtx));
Assert.assertTrue(profileRequestCtx.ensureOutboundMessageContext()
- .getMessage() instanceof CredentialIssuerMetadataSuccessResponse);
+ .getMessage() instanceof JSONSuccessResponse);
}
@DataProvider(name = "unsignedAccept")
@@ -304,7 +302,7 @@ public class FormOutboundIssuerMetadataResponseMessageTest {
actionOf(CredentialIssuerMetadata.parse(members())).execute(requestCtx));
Assert.assertTrue(profileRequestCtx.ensureOutboundMessageContext()
- .getMessage() instanceof CredentialIssuerMetadataSuccessResponse);
+ .getMessage() instanceof JSONSuccessResponse);
}
@Test
@@ -379,7 +377,7 @@ public class FormOutboundIssuerMetadataResponseMessageTest {
.ensureOutboundMessageContext().getMessage()).toHTTPResponse();
Assert.assertEquals(response.getStatusCode(), 200);
Assert.assertEquals(response.getEntityContentType().getType(), ContentType.APPLICATION_JWT.getType());
- Assert.assertEquals(response.getHeaderMap().get("Vary"), List.of("Accept"));
+ Assert.assertEquals(httpResponse.getHeaders("Vary"), List.of("Accept"));
}
@Test
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list