Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/tck/sample.tck.properties
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
# Contains sample configuration options
dataspacetck.test.package=org.eclipse.dataspacetck.dcp.verification.presentation
#dataspacetck.test.package=org.eclipse.dataspacetck.dcp.verification.issuance.cs
dataspacetck.credentials.correlation.id=foobar
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2025 Metaform Systems Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Metaform Systems Inc. - initial API and implementation
*
*/

package org.eclipse.dataspacetck.dcp.system.annotation;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Annotation used to inject randomly generated credentials of the given type into a test method
*/
@Inherited
@Retention(RUNTIME)
@Target({FIELD, PARAMETER})
public @interface Credential {
String value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2025 Metaform Systems Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Metaform Systems Inc. - initial API and implementation
*
*/

package org.eclipse.dataspacetck.dcp.system.annotation;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Holder-assigned Process Identifier (PID) when dealing with Credential Issuance messages
*/
@Inherited
@Retention(RUNTIME)
@Target({FIELD, PARAMETER})
public @interface HolderPid {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2025 Metaform Systems Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Metaform Systems Inc. - initial API and implementation
*
*/

package org.eclipse.dataspacetck.dcp.system.annotation;

import org.eclipse.dataspacetck.core.api.system.Inject;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* For field injection, used in conjunction with {@link Inject} to specify the injection of a verifier service.
*/
@Inherited
@Retention(RUNTIME)
@Target({FIELD, PARAMETER})
public @interface Issuer {
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
* A holder, verifier or third-party.
*/
public enum RoleType {
HOLDER, VERIFIER, THIRD_PARTY
HOLDER, ISSUER, VERIFIER, THIRD_PARTY
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@

package org.eclipse.dataspacetck.dcp.system.cs;

import org.eclipse.dataspacetck.dcp.system.model.vc.VcContainer;
import org.eclipse.dataspacetck.dcp.system.service.Result;

import java.util.List;
import java.io.InputStream;
import java.util.Map;

/**
Expand All @@ -33,5 +32,5 @@ public interface CredentialService {
/**
* Writes issued credentials.
*/
Result<Void> writeCredentials(String bearerDid, String correlationId, List<VcContainer> containers);
Result<Void> writeCredentials(String idTokenJwt, InputStream body);
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public interface DcpConstants {

String PRESENTATION_QUERY_PATH = "/presentations/query";

String CREDENTIALS_PATH = "/credentials";

String CREDENTIAL_OFFER_MESSAGE_TYPE = "CredentialOfferMessage";

String CREDENTIAL_MESSAGE_TYPE = "CredentialMessage";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@
* Result of a service invocation.
*/
public class Result<T> {
public enum ErrorType {
NOT_FOUND, UNAUTHORIZED, BAD_REQUEST, GENERAL_ERROR, NO_ERROR
}

private final T content;
private final String failure;
private final ErrorType errorType;

private Result(T content, String failure, ErrorType errorType) {
this.content = content;
this.failure = failure;
this.errorType = errorType;
}

public static Result<Void> success() {
return new Result<>(null, null, ErrorType.NO_ERROR);
}
Expand All @@ -34,6 +36,14 @@ public static <T> Result<T> success(T content) {
return new Result<>(content, null, ErrorType.NO_ERROR);
}

public static <T> Result<T> failure(String failure) {
return new Result<>(null, failure, ErrorType.GENERAL_ERROR);
}

public static <T> Result<T> failure(String failure, ErrorType errorType) {
return new Result<>(null, failure, errorType);
}

public boolean succeeded() {
return failure == null;
}
Expand All @@ -54,22 +64,12 @@ public ErrorType getErrorType() {
return errorType;
}

public static <T> Result<T> failure(String failure) {
return new Result<>(null, failure, ErrorType.GENERAL_ERROR);
}

public static <T> Result<T> failure(String failure, ErrorType errorType) {
return new Result<>(null, failure, errorType);
}

public <R> R convert() {
//noinspection unchecked
return (R) this;
}

private Result(T content, String failure, ErrorType errorType) {
this.content = content;
this.failure = failure;
this.errorType = errorType;
public enum ErrorType {
NOT_FOUND, UNAUTHORIZED, BAD_REQUEST, GENERAL_ERROR, NO_ERROR
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@
import org.eclipse.dataspacetck.core.spi.system.SystemConfiguration;
import org.eclipse.dataspacetck.core.spi.system.SystemLauncher;
import org.eclipse.dataspacetck.dcp.system.annotation.AuthToken;
import org.eclipse.dataspacetck.dcp.system.annotation.Credential;
import org.eclipse.dataspacetck.dcp.system.annotation.Did;
import org.eclipse.dataspacetck.dcp.system.annotation.Holder;
import org.eclipse.dataspacetck.dcp.system.annotation.HolderPid;
import org.eclipse.dataspacetck.dcp.system.annotation.IssueCredentials;
import org.eclipse.dataspacetck.dcp.system.annotation.Issuer;
import org.eclipse.dataspacetck.dcp.system.annotation.ThirdParty;
import org.eclipse.dataspacetck.dcp.system.annotation.Verifier;
import org.eclipse.dataspacetck.dcp.system.assembly.BaseAssembly;
import org.eclipse.dataspacetck.dcp.system.assembly.ServiceAssembly;
import org.eclipse.dataspacetck.dcp.system.crypto.KeyService;
import org.eclipse.dataspacetck.dcp.system.cs.CredentialService;
import org.eclipse.dataspacetck.dcp.system.did.DidService;
import org.eclipse.dataspacetck.dcp.system.generation.JwtCredentialGenerator;
import org.eclipse.dataspacetck.dcp.system.model.vc.VcContainer;
import org.jetbrains.annotations.Nullable;

import java.lang.annotation.Annotation;
Expand All @@ -55,7 +60,8 @@ public <T> boolean providesService(Class<T> type) {
return type.isAssignableFrom(CredentialService.class) ||
type.isAssignableFrom(DidService.class) ||
type.isAssignableFrom(String.class) ||
type.isAssignableFrom(KeyService.class);
type.isAssignableFrom(KeyService.class) ||
type.isAssignableFrom(VcContainer.class);
}

@Nullable
Expand All @@ -65,13 +71,23 @@ public <T> T getService(Class<T> type, ServiceConfiguration configuration, Servi
var assembly = serviceAssemblies.computeIfAbsent(scopeId, id -> new ServiceAssembly(baseAssembly, resolver, configuration));
if (type.isAssignableFrom(CredentialService.class)) {
return type.cast(assembly.getCredentialService());
} else if (type.isAssignableFrom(VcContainer.class)) {
if (hasAnnotation(Credential.class, configuration)) {
var gen = new JwtCredentialGenerator(baseAssembly.getIssuerDid(), baseAssembly.getIssuerKeyService());
var credentialType = getAnnotation(Credential.class, configuration);
if (credentialType.isPresent()) {
return type.cast(assembly.createVcContainer(baseAssembly.getIssuerDid(), baseAssembly.getHolderDid(), gen, credentialType.get().value()));
}
}
} else if (type.isAssignableFrom(KeyService.class)) {
if (hasAnnotation(Verifier.class, configuration)) {
return type.cast(baseAssembly.getVerifierKeyService());
} else if (hasAnnotation(Holder.class, configuration)) {
return type.cast(baseAssembly.getHolderKeyService());
} else if (hasAnnotation(ThirdParty.class, configuration)) {
return type.cast(baseAssembly.getThirdPartyKeyService());
} else if (hasAnnotation(Issuer.class, configuration)) {
return type.cast(baseAssembly.getIssuerKeyService());
}
} else if (type.isAssignableFrom(DidService.class)) {
if (hasAnnotation(Verifier.class, configuration)) {
Expand All @@ -80,11 +96,16 @@ public <T> T getService(Class<T> type, ServiceConfiguration configuration, Servi
return type.cast(baseAssembly.getHolderDidService());
} else if (hasAnnotation(ThirdParty.class, configuration)) {
return type.cast(baseAssembly.getThirdPartyDidService());
} else if (hasAnnotation(Issuer.class, configuration)) {
return type.cast(baseAssembly.getIssuerDidService());
}
} else if (type.isAssignableFrom(String.class)) {
if (hasAnnotation(AuthToken.class, configuration)) {
return createAuthToken(type, configuration, assembly);
}
if (hasAnnotation(HolderPid.class, configuration)) {
return type.cast(baseAssembly.getHolderPid());
}

var did = getAnnotation(Did.class, configuration);
if (did.isPresent()) {
Expand All @@ -98,9 +119,10 @@ public <T> T getService(Class<T> type, ServiceConfiguration configuration, Servi
case THIRD_PARTY -> {
return type.cast(baseAssembly.getThirdPartyDid());
}
default -> {
throw new UnsupportedOperationException("Unsupported DID role: " + did.get().value());
case ISSUER -> {
return type.cast(baseAssembly.getIssuerDid());
}
default -> throw new UnsupportedOperationException("Unsupported DID role: " + did.get().value());
}
}
}
Expand All @@ -110,7 +132,7 @@ public <T> T getService(Class<T> type, ServiceConfiguration configuration, Servi
@Override
public void beforeExecution(ServiceConfiguration configuration, ServiceResolver resolver) {
if (hasAnnotation(IssueCredentials.class, configuration)) {
// TODO implement credential issuance
serviceAssemblies.get(configuration.getScopeId()).issueCredentials(baseAssembly);
}
}

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

import static java.lang.String.format;
import static java.util.Optional.ofNullable;
import static java.util.UUID.randomUUID;
import static org.eclipse.dataspacetck.core.api.system.SystemsConstants.TCK_CALLBACK_ADDRESS;
import static org.eclipse.dataspacetck.core.api.system.SystemsConstants.TCK_DEFAULT_CALLBACK_ADDRESS;
import static org.eclipse.dataspacetck.core.api.system.SystemsConstants.TCK_PREFIX;
Expand All @@ -52,6 +54,7 @@ public class BaseAssembly {
private final KeyServiceImpl thirdPartyKeyService;
private final DidServiceImpl thirdPartyDidService;
private final ObjectMapper mapper;
private final String holderPid;

public BaseAssembly(SystemConfiguration configuration) {
mapper = new ObjectMapper();
Expand All @@ -68,6 +71,8 @@ public BaseAssembly(SystemConfiguration configuration) {
holderDidService = new DidServiceImpl(holderDid, address, holderKeyService);
holderTokenService = new TokenValidationServiceImpl(holderDid);

holderPid = ofNullable(configuration.getPropertyAsString(TCK_PREFIX + ".credentials.correlation.id", null)).orElseGet(() -> randomUUID().toString());

verifierTokenService = new TokenValidationServiceImpl(verifierDid);
verifierKeyService = new KeyServiceImpl(Keys.generateEcKey());
verifierDidService = new DidServiceImpl(verifierDid, address, verifierKeyService);
Expand Down Expand Up @@ -145,4 +150,9 @@ private String parseDid(String discriminator) {
return uri.getPort() != 443 ? format("did:web:%s%%3A%s:%s", uri.getHost(), uri.getPort(), discriminator)
: format("did:web:%s:%s", uri.getHost(), discriminator);
}

public String getHolderPid() {
return holderPid;
}

}
Loading