Skip to content

Commit

Permalink
feat: adds support for dcp v1.0 in default credential service client (#…
Browse files Browse the repository at this point in the history
…4780)

* feat: add support for dcp v1.0 in default credential service client with backward compatibility option

* pr suggestions
  • Loading branch information
wolf4ood authored Feb 3, 2025
1 parent 893f6ca commit d9083ce
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService;
import org.eclipse.edc.iam.identitytrust.spi.validation.TokenValidationAction;
import org.eclipse.edc.iam.identitytrust.spi.verification.SignatureSuiteRegistry;
import org.eclipse.edc.iam.identitytrust.transform.to.JsonObjectToPresentationResponseMessageTransformer;
import org.eclipse.edc.iam.verifiablecredentials.VerifiableCredentialValidationServiceImpl;
import org.eclipse.edc.iam.verifiablecredentials.revocation.bitstring.BitstringStatusListRevocationService;
import org.eclipse.edc.iam.verifiablecredentials.revocation.statuslist2021.StatusList2021RevocationService;
Expand All @@ -37,6 +38,7 @@
import org.eclipse.edc.iam.verifiablecredentials.spi.validation.PresentationVerifier;
import org.eclipse.edc.iam.verifiablecredentials.spi.validation.TrustedIssuerRegistry;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.jsonld.spi.JsonLdNamespace;
import org.eclipse.edc.jwt.validation.jti.JtiValidationStore;
import org.eclipse.edc.participant.spi.ParticipantAgentService;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
Expand Down Expand Up @@ -70,6 +72,10 @@
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DCP_CONTEXT_URL;
import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_0_8;
import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_NAMESPACE_V_1_0;
import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_V_1_0_CONTEXT;
import static org.eclipse.edc.iam.verifiablecredentials.spi.VcConstants.STATUSLIST_2021_URL;
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;
import static org.eclipse.edc.verifiablecredentials.jwt.JwtPresentationVerifier.JWT_VC_TOKEN_CONTEXT;
Expand All @@ -79,6 +85,7 @@ public class IdentityAndTrustExtension implements ServiceExtension {

public static final long DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS = 15 * 60 * 1000L;
public static final String DCP_SELF_ISSUED_TOKEN_CONTEXT = "dcp-si";
public static final String DCP_CLIENT_CONTEXT = "dcp-client";
public static final String JSON_2020_SIGNATURE_SUITE = "JsonWebSignature2020";
public static final long DEFAULT_CLEANUP_PERIOD_SECONDS = 60;
@Setting(description = "Validity period of cached StatusList2021 credential entries in milliseconds.", defaultValue = DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS + "", key = "edc.iam.credential.revocation.cache.validity")
Expand All @@ -87,6 +94,10 @@ public class IdentityAndTrustExtension implements ServiceExtension {
private String issuerId;
@Setting(description = "The period of the JTI entry reaper thread in seconds", defaultValue = DEFAULT_CLEANUP_PERIOD_SECONDS + "", key = "edc.sql.store.jti.cleanup.period")
private long reaperCleanupPeriod;

@Setting(description = "If set enable the dcp v0.8 namespace will be used", key = "edc.dcp.v08.forced", required = false, defaultValue = "false")
private boolean enableDcpV08;

@Inject
private SecureTokenService secureTokenService;

Expand Down Expand Up @@ -201,8 +212,13 @@ public IdentityService createIdentityService(ServiceExtensionContext context) {
@Provider
public CredentialServiceClient getCredentialServiceClient(ServiceExtensionContext context) {
if (credentialServiceClient == null) {

var clientTypeTransformerRegistry = typeTransformerRegistry.forContext(DCP_CLIENT_CONTEXT);
clientTypeTransformerRegistry.register(new JsonObjectToPresentationResponseMessageTransformer(typeManager, JSON_LD, dcpNamespace()));


credentialServiceClient = new DefaultCredentialServiceClient(httpClient, Json.createBuilderFactory(Map.of()),
typeManager, JSON_LD, typeTransformerRegistry, jsonLd, context.getMonitor());
typeManager, JSON_LD, clientTypeTransformerRegistry, jsonLd, context.getMonitor(), dcpContext());
}
return credentialServiceClient;
}
Expand All @@ -225,6 +241,13 @@ public PresentationVerifier createPresentationVerifier(ServiceExtensionContext c
return presentationVerifier;
}

private JsonLdNamespace dcpNamespace() {
return enableDcpV08 ? DSPACE_DCP_NAMESPACE_V_0_8 : DSPACE_DCP_NAMESPACE_V_1_0;
}

private String dcpContext() {
return enableDcpV08 ? DCP_CONTEXT_URL : DSPACE_DCP_V_1_0_CONTEXT;
}

@NotNull
private TokenValidationAction tokenValidationAction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import okhttp3.RequestBody;
import org.eclipse.edc.http.spi.EdcHttpClient;
import org.eclipse.edc.iam.identitytrust.spi.CredentialServiceClient;
import org.eclipse.edc.iam.identitytrust.spi.DcpConstants;
import org.eclipse.edc.iam.identitytrust.spi.model.PresentationQueryMessage;
import org.eclipse.edc.iam.identitytrust.spi.model.PresentationResponseMessage;
import org.eclipse.edc.iam.verifiablecredentials.spi.VcConstants;
Expand Down Expand Up @@ -55,15 +54,17 @@ public class DefaultCredentialServiceClient implements CredentialServiceClient {
private final TypeTransformerRegistry transformerRegistry;
private final JsonLd jsonLd;
private final Monitor monitor;
private final String dcpContextUrl;

public DefaultCredentialServiceClient(EdcHttpClient httpClient, JsonBuilderFactory jsonFactory, TypeManager typeManager, String typeContext, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, Monitor monitor) {
public DefaultCredentialServiceClient(EdcHttpClient httpClient, JsonBuilderFactory jsonFactory, TypeManager typeManager, String typeContext, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, Monitor monitor, String dcpContextUrl) {
this.httpClient = httpClient;
this.jsonFactory = jsonFactory;
this.typeManager = typeManager;
this.typeContext = typeContext;
this.transformerRegistry = transformerRegistry;
this.jsonLd = jsonLd;
this.monitor = monitor;
this.dcpContextUrl = dcpContextUrl;
}

@Override
Expand Down Expand Up @@ -154,7 +155,7 @@ private JsonObject createPresentationQuery(List<String> scopes) {
return jsonFactory.createObjectBuilder()
.add(JsonLdKeywords.CONTEXT, jsonFactory.createArrayBuilder()
.add(VcConstants.PRESENTATION_EXCHANGE_URL)
.add(DcpConstants.DCP_CONTEXT_URL))
.add(dcpContextUrl))
.add(JsonLdKeywords.TYPE, PresentationQueryMessage.PRESENTATION_QUERY_MESSAGE_TERM)
.add("scope", scopeArray.build())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.configuration.ConfigFactory;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -33,6 +34,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.eclipse.edc.iam.identitytrust.core.IdentityAndTrustExtension.DCP_CLIENT_CONTEXT;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
Expand All @@ -44,19 +46,22 @@ class IdentityAndTrustExtensionTest {
private static final String CONNECTOR_DID_PROPERTY = "edc.iam.issuer.id";
private static final String CLEANUP_PERIOD = "edc.sql.store.jti.cleanup.period";
private final JtiValidationStore storeMock = mock();
private final TypeTransformerRegistry transformerRegistry = mock();

@BeforeEach
void setUp(ServiceExtensionContext context) {
context.registerService(SecureTokenService.class, mock());
context.registerService(TypeManager.class, new JacksonTypeManager());
context.registerService(JtiValidationStore.class, storeMock);
context.registerService(ExecutorInstrumentation.class, ExecutorInstrumentation.noop());
context.registerService(TypeTransformerRegistry.class, transformerRegistry);

var config = ConfigFactory.fromMap(Map.of(
CONNECTOR_DID_PROPERTY, "did:web:test",
CLEANUP_PERIOD, "1"
));
when(context.getConfig()).thenReturn(config);
when(transformerRegistry.forContext(DCP_CLIENT_CONTEXT)).thenReturn(transformerRegistry);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import java.util.Objects;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.edc.iam.identitytrust.spi.DcpConstants.DSPACE_DCP_V_1_0_CONTEXT;
import static org.eclipse.edc.junit.testfixtures.TestUtils.getResourceFileContentAsString;
import static org.eclipse.edc.spi.result.Result.success;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -96,7 +97,7 @@ void setup() {
var jsonLdMock = mock(JsonLd.class);
when(jsonLdMock.expand(any())).thenAnswer(a -> success(a.getArgument(0)));
client = new DefaultCredentialServiceClient(httpClientMock, Json.createBuilderFactory(Map.of()),
typeManager, "test", transformerRegistry, jsonLdMock, mock());
typeManager, "test", transformerRegistry, jsonLdMock, mock(), DSPACE_DCP_V_1_0_CONTEXT);

when(typeManager.getMapper("test")).thenReturn(JacksonJsonLd.createObjectMapper());
}
Expand Down

0 comments on commit d9083ce

Please sign in to comment.