From ab9fdf76e1dd2b6c7c1731e81ef4a39a4b068375 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Tue, 7 Nov 2023 07:07:41 +0100 Subject: [PATCH] chore: add latest JSON-LD context to cache --- .../api/PresentationApiExtension.java | 18 +-- .../edc/identityservice/api/v1/ApiSchema.java | 6 +- .../api/v1/PresentationApi.java | 4 +- .../PresentationQueryValidator.java | 6 +- .../resources/presentation-query.v08.json | 12 -- .../PresentationQueryValidatorTest.java | 4 +- core/identity-hub-core/build.gradle.kts | 1 + .../core/CoreServicesExtension.java | 27 +++- .../resources/presentation-exchange.v1.json | 0 .../resources/presentation-query.v08.json | 116 ++++++++++++++++++ ...ectToPresentationQueryTransformerTest.java | 4 +- .../test/resources/presentation_query.json | 4 +- .../tests/ResolutionApiEndToEndTest.java | 4 +- .../spi/model/PresentationQuery.java | 2 +- 14 files changed, 162 insertions(+), 46 deletions(-) delete mode 100644 core/identity-hub-api/src/main/resources/presentation-query.v08.json rename core/{identity-hub-api => identity-hub-core}/src/main/resources/presentation-exchange.v1.json (100%) create mode 100644 core/identity-hub-core/src/main/resources/presentation-query.v08.json diff --git a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/PresentationApiExtension.java b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/PresentationApiExtension.java index 5beb0a2c9..cb0616abb 100644 --- a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/PresentationApiExtension.java +++ b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/PresentationApiExtension.java @@ -34,10 +34,6 @@ import org.eclipse.edc.web.jersey.jsonld.ObjectMapperProvider; import org.eclipse.edc.web.spi.WebService; -import java.net.URISyntaxException; - -import static org.eclipse.edc.identityhub.spi.model.IdentityHubConstants.IATP_CONTEXT_URL; -import static org.eclipse.edc.identityhub.spi.model.IdentityHubConstants.PRESENTATION_EXCHANGE_URL; import static org.eclipse.edc.spi.CoreConstants.JSON_LD; @Extension(value = "Presentation API Extension") @@ -45,8 +41,7 @@ public class PresentationApiExtension implements ServiceExtension { public static final String RESOLUTION_SCOPE = "resolution-scope"; public static final String RESOLUTION_CONTEXT = "resolution"; - public static final String PRESENTATION_EXCHANGE_V_1_JSON = "presentation-exchange.v1.json"; - public static final String PRESENTATION_QUERY_V_08_JSON = "presentation-query.v08.json"; + @Inject private TypeTransformerRegistry typeTransformer; @@ -77,8 +72,6 @@ public void initialize(ServiceExtensionContext context) { validatorRegistry.register(PresentationQuery.PRESENTATION_QUERY_TYPE_PROPERTY, new PresentationQueryValidator()); - // Setup API - cacheContextDocuments(getClass().getClassLoader()); var controller = new PresentationApiController(validatorRegistry, typeTransformer, credentialResolver, accessTokenVerifier, presentationGenerator, context.getMonitor()); var jsonLdMapper = typeManager.getMapper(JSON_LD); @@ -91,12 +84,5 @@ public void initialize(ServiceExtensionContext context) { typeTransformer.register(new JsonValueToGenericTypeTransformer(jsonLdMapper)); } - private void cacheContextDocuments(ClassLoader classLoader) { - try { - jsonLd.registerCachedDocument(PRESENTATION_EXCHANGE_URL, classLoader.getResource(PRESENTATION_EXCHANGE_V_1_JSON).toURI()); - jsonLd.registerCachedDocument(IATP_CONTEXT_URL, classLoader.getResource(PRESENTATION_QUERY_V_08_JSON).toURI()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } + } diff --git a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/ApiSchema.java b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/ApiSchema.java index 55cbdfe13..551f9fba9 100644 --- a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/ApiSchema.java +++ b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/ApiSchema.java @@ -49,7 +49,7 @@ record PresentationQuerySchema( String type, @Schema(name = "scope", requiredMode = NOT_REQUIRED) List scope, - @Schema(name = "presentation_definition", requiredMode = NOT_REQUIRED) + @Schema(name = "presentationDefinition", requiredMode = NOT_REQUIRED) PresentationDefinitionSchema presentationDefinitionSchema ) { @@ -60,7 +60,7 @@ record PresentationQuerySchema( "https://identity.foundation/presentation-exchange/submission/v1" ], "@type": "Query", - "presentation_definition": null, + "presentationDefinition": null, "scope": [ "org.eclipse.edc.vc.type:SomeCredential_0.3.5:write, "org.eclipse.edc.vc.type:SomeOtherCredential:read, @@ -83,7 +83,7 @@ record PresentationDefinitionSchema() { private static final String EXAMPLE = """ { "comment": "taken from https://identity.foundation/presentation-exchange/spec/v2.0.0/#presentation-definition" - "presentation_definition": { + "presentationDefinition": { "id": "first simple example", "input_descriptors": [ { diff --git a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/PresentationApi.java b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/PresentationApi.java index 56be59050..30153348a 100644 --- a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/PresentationApi.java +++ b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/v1/PresentationApi.java @@ -49,14 +49,14 @@ public interface PresentationApi { responses = { @ApiResponse(responseCode = "200", description = "The query was successfully processed, the response contains the VerifiablePresentation", content = @Content(schema = @Schema(implementation = PresentationResponse.class), mediaType = "application/ld+json")), - @ApiResponse(responseCode = "400", description = "Request body was malformed, for example when both scope and presentation_definition are given", + @ApiResponse(responseCode = "400", description = "Request body was malformed, for example when both scope and presentationDefinition are given", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetailSchema.class)), mediaType = "application/json")), @ApiResponse(responseCode = "401", description = "No Authorization header was given.", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetailSchema.class)), mediaType = "application/json")), @ApiResponse(responseCode = "403", description = "The given authentication token could not be validated. This can happen, when the request body " + "calls for a broader query scope than the granted scope in the auth token", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetailSchema.class)), mediaType = "application/json")), - @ApiResponse(responseCode = "501", description = "When the request contained a presentation_definition object, but the implementation does not support it.", + @ApiResponse(responseCode = "501", description = "When the request contained a presentationDefinition object, but the implementation does not support it.", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetailSchema.class)), mediaType = "application/json")) } ) diff --git a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidator.java b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidator.java index 67b43cbb5..03cfb6e34 100644 --- a/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidator.java +++ b/core/identity-hub-api/src/main/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidator.java @@ -25,7 +25,7 @@ /** * Validates, that a JsonObject representing a {@link PresentationQuery} contains either a {@code scope} property, - * or a {@code presentation_definition} query. + * or a {@code presentationDefinition} query. */ public class PresentationQueryValidator implements Validator { @Override @@ -35,11 +35,11 @@ public ValidationResult validate(JsonObject input) { var presentationDef = input.get(PresentationQuery.PRESENTATION_QUERY_DEFINITION_PROPERTY); if (scope == null && presentationDef == null) { - return failure(violation("Must contain either a 'scope' or a 'presentation_definition' property.", null)); + return failure(violation("Must contain either a 'scope' or a 'presentationDefinition' property.", null)); } if (scope != null && presentationDef != null) { - return failure(violation("Must contain either a 'scope' or a 'presentation_definition', not both.", null)); + return failure(violation("Must contain either a 'scope' or a 'presentationDefinition', not both.", null)); } return success(); diff --git a/core/identity-hub-api/src/main/resources/presentation-query.v08.json b/core/identity-hub-api/src/main/resources/presentation-query.v08.json deleted file mode 100644 index ee45d6f63..000000000 --- a/core/identity-hub-api/src/main/resources/presentation-query.v08.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "@context": { - "scope": { - "@id": "https://w3id.org/tractusx-trust/v0.8/scope", - "@container": "@set" - }, - "presentation_definition":{ - "@id": "https://w3id.org/tractusx-trust/v0.8/presentation_definition", - "@type": "@json" - } - } -} \ No newline at end of file diff --git a/core/identity-hub-api/src/test/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidatorTest.java b/core/identity-hub-api/src/test/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidatorTest.java index 1e1fde340..182c2b2ae 100644 --- a/core/identity-hub-api/src/test/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidatorTest.java +++ b/core/identity-hub-api/src/test/java/org/eclipse/edc/identityservice/api/validation/PresentationQueryValidatorTest.java @@ -70,7 +70,7 @@ void validate_withPresentationDefinition_success() throws JsonProcessingExceptio @Test void validate_withNone_fails() { var jo = createObjectBuilder().build(); - assertThat(validator.validate(jo)).isFailed().detail().contains("Must contain either a 'scope' or a 'presentation_definition' property."); + assertThat(validator.validate(jo)).isFailed().detail().contains("Must contain either a 'scope' or a 'presentationDefinition' property."); } @Test @@ -84,7 +84,7 @@ void validate_withBoth_fails() throws JsonProcessingException { .add(PresentationQuery.PRESENTATION_QUERY_DEFINITION_PROPERTY, createPresentationDefArray(presDef)) .build(); - assertThat(validator.validate(jo)).isFailed().detail().contains("Must contain either a 'scope' or a 'presentation_definition', not both."); + assertThat(validator.validate(jo)).isFailed().detail().contains("Must contain either a 'scope' or a 'presentationDefinition', not both."); } private JsonArray createScopeArray() { diff --git a/core/identity-hub-core/build.gradle.kts b/core/identity-hub-core/build.gradle.kts index 4495ec2b6..f6a88c71b 100644 --- a/core/identity-hub-core/build.gradle.kts +++ b/core/identity-hub-core/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { api(project(":spi:identity-hub-spi")) + implementation(libs.edc.spi.jsonld) implementation(libs.edc.iatp.service) // JWT validator implementation(libs.edc.core.crypto) // JWT verifier implementation(libs.nimbus.jwt) diff --git a/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java b/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java index fc6d44c65..36db996cb 100644 --- a/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java +++ b/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java @@ -21,6 +21,7 @@ import org.eclipse.edc.identityhub.token.verification.AccessTokenVerifierImpl; import org.eclipse.edc.identitytrust.validation.JwtValidator; import org.eclipse.edc.identitytrust.verification.JwtVerifier; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; @@ -29,6 +30,11 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.verification.jwt.SelfIssuedIdTokenVerifier; +import java.net.URISyntaxException; + +import static org.eclipse.edc.identityhub.spi.model.IdentityHubConstants.IATP_CONTEXT_URL; +import static org.eclipse.edc.identityhub.spi.model.IdentityHubConstants.PRESENTATION_EXCHANGE_URL; + /** * This extension provides some core services for the IdentityHub, such as: *
    @@ -42,15 +48,25 @@ public class CoreServicesExtension implements ServiceExtension { @Setting(value = "Configure this IdentityHub's DID", required = true) public static final String OWN_DID_PROPERTY = "edc.ih.iam.id"; + public static final String PRESENTATION_EXCHANGE_V_1_JSON = "presentation-exchange.v1.json"; + public static final String PRESENTATION_QUERY_V_08_JSON = "presentation-query.v08.json"; private JwtVerifier jwtVerifier; private JwtValidator jwtValidator; - @Inject private DidResolverRegistry didResolverRegistry; @Inject private PublicKeyWrapper identityHubPublicKey; + @Inject + private JsonLd jsonLd; + + @Override + public void initialize(ServiceExtensionContext context) { + // Setup API + cacheContextDocuments(getClass().getClassLoader()); + } + @Provider public AccessTokenVerifier createAccessTokenVerifier(ServiceExtensionContext context) { return new AccessTokenVerifierImpl(getJwtVerifier(), getJwtValidator(), getOwnDid(context), identityHubPublicKey); @@ -75,4 +91,13 @@ public JwtVerifier getJwtVerifier() { private String getOwnDid(ServiceExtensionContext context) { return context.getConfig().getString(OWN_DID_PROPERTY); } + + private void cacheContextDocuments(ClassLoader classLoader) { + try { + jsonLd.registerCachedDocument(PRESENTATION_EXCHANGE_URL, classLoader.getResource(PRESENTATION_EXCHANGE_V_1_JSON).toURI()); + jsonLd.registerCachedDocument(IATP_CONTEXT_URL, classLoader.getResource(PRESENTATION_QUERY_V_08_JSON).toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } } diff --git a/core/identity-hub-api/src/main/resources/presentation-exchange.v1.json b/core/identity-hub-core/src/main/resources/presentation-exchange.v1.json similarity index 100% rename from core/identity-hub-api/src/main/resources/presentation-exchange.v1.json rename to core/identity-hub-core/src/main/resources/presentation-exchange.v1.json diff --git a/core/identity-hub-core/src/main/resources/presentation-query.v08.json b/core/identity-hub-core/src/main/resources/presentation-query.v08.json new file mode 100644 index 000000000..564965f08 --- /dev/null +++ b/core/identity-hub-core/src/main/resources/presentation-query.v08.json @@ -0,0 +1,116 @@ +{ + "@context": { + "@version": 1.1, + "@protected": true, + "iatp": "https://w3id.org/tractusx-trust/v0.8/", + "cred": "https://www.w3.org/2018/credentials/", + "xsd": "http://www.w3.org/2001/XMLSchema/", + "CredentialContainer": { + "@id": "iatp:CredentialContainer", + "@context": { + "payload": { + "@id": "iatp:payload", + "@type": "xsd:string" + } + } + }, + "CredentialMessage": { + "@id": "iatp:CredentialMessage", + "@context": { + "credentials": "iatp:credentials" + } + }, + "CredentialObject": { + "@id": "iatp:CredentialObject", + "@context": { + "credentialType": { + "@id": "iatp:credentialType", + "@container": "@set" + }, + "format": "iatp:format", + "offerReason": { + "@id": "iatp:offerReason", + "@type": "xsd:string" + }, + "bindingMethods": { + "@id": "iatp:bindingMethods", + "@type": "xsd:string", + "@container": "@set" + }, + "cryptographicSuites": { + "@id": "iatp:cryptographicSuites", + "@type": "xsd:string", + "@container": "@set" + }, + "issuancePolicy": "iatp:issuancePolicy" + } + }, + "CredentialOfferMessage": { + "@id": "iatp:CredentialOfferMessage", + "@context": { + "credentialIssuer": "cred:issuer", + "credentials": "iatp:credentials" + } + }, + "CredentialRequestMessage": { + "@id": "iatp:CredentialRequestMessage", + "@context": { + "format": "iatp:format", + "type": "@type" + } + }, + "CredentialService": "iatp:CredentialService", + "CredentialStatus": { + "@id": "iatp:CredentialStatus", + "@context": { + "requestId": { + "@id": "iatp:requestId", + "@type": "@id" + }, + "status": { + "@id": "iatp:status", + "@type": "xsd:string" + } + } + }, + "IssuerMetadata": { + "@id": "iatp:IssuerMetadata", + "@context": { + "credentialIssuer": "cred:issuer", + "credentialsSupported": { + "@id": "iatp:credentialsSupported", + "@container": "@set" + } + } + }, + "PresentationQueryMessage": { + "@id": "iatp:PresentationQueryMessage", + "@context": { + "presentationDefinition": "iatp:presentationDefinition", + "scope": "iatp:scope" + } + }, + "credentials": { + "@id": "iatp:credentials", + "@container": "@set" + }, + "credentialSubject": { + "@id": "iatp:credentialSubject", + "@type": "cred:credentialSubject" + }, + "format": { + "@id": "iatp:format", + "@type": "xsd:string" + }, + "presentationDefinition": { + "@id": "iatp:presentationDefinition", + "@type": "@json" + }, + "scope": { + "@id": "iatp:scope", + "@type": "xsd:string", + "@container": "@set" + }, + "type": "@type" + } +} \ No newline at end of file diff --git a/core/identity-hub-transform/src/test/java/org/eclipse/edc/identityhub/transform/JsonObjectToPresentationQueryTransformerTest.java b/core/identity-hub-transform/src/test/java/org/eclipse/edc/identityhub/transform/JsonObjectToPresentationQueryTransformerTest.java index 8a88daa29..ebd72f333 100644 --- a/core/identity-hub-transform/src/test/java/org/eclipse/edc/identityhub/transform/JsonObjectToPresentationQueryTransformerTest.java +++ b/core/identity-hub-transform/src/test/java/org/eclipse/edc/identityhub/transform/JsonObjectToPresentationQueryTransformerTest.java @@ -86,7 +86,7 @@ void transform_withPresentationDefinition() throws JsonProcessingException { "https://w3id.org/tractusx-trust/v0.8" ], "@type": "Query", - "presentation_definition": { + "presentationDefinition": { "id": "first simple example", "input_descriptors": [ { @@ -135,7 +135,7 @@ void transform_withScopesAndPresDef() throws JsonProcessingException { ], "@type": "Query", "scope": ["test-scope1"], - "presentation_definition": { + "presentationDefinition": { "id": "first simple example", "input_descriptors": [ { diff --git a/core/identity-hub-transform/src/test/resources/presentation_query.json b/core/identity-hub-transform/src/test/resources/presentation_query.json index ee45d6f63..740434b72 100644 --- a/core/identity-hub-transform/src/test/resources/presentation_query.json +++ b/core/identity-hub-transform/src/test/resources/presentation_query.json @@ -4,8 +4,8 @@ "@id": "https://w3id.org/tractusx-trust/v0.8/scope", "@container": "@set" }, - "presentation_definition":{ - "@id": "https://w3id.org/tractusx-trust/v0.8/presentation_definition", + "presentationDefinition": { + "@id": "https://w3id.org/tractusx-trust/v0.8/presentationDefinition", "@type": "@json" } } diff --git a/e2e-tests/api-tests/src/test/java/org/eclipse/edc/identityhub/tests/ResolutionApiEndToEndTest.java b/e2e-tests/api-tests/src/test/java/org/eclipse/edc/identityhub/tests/ResolutionApiEndToEndTest.java index 51107fc44..9d2d7df5e 100644 --- a/e2e-tests/api-tests/src/test/java/org/eclipse/edc/identityhub/tests/ResolutionApiEndToEndTest.java +++ b/e2e-tests/api-tests/src/test/java/org/eclipse/edc/identityhub/tests/ResolutionApiEndToEndTest.java @@ -66,7 +66,7 @@ public class ResolutionApiEndToEndTest { private static final CredentialQueryResolver CREDENTIAL_QUERY_RESOLVER = mock(); private static final PresentationGenerator PRESENTATION_GENERATOR = mock(); private static final AccessTokenVerifier ACCESS_TOKEN_VERIFIER = mock(); - + @RegisterExtension static EdcRuntimeExtension runtime; @@ -121,7 +121,7 @@ void query_withPresentationDefinition_shouldReturn503() { "https://w3id.org/tractusx-trust/v0.8" ], "@type": "Query", - "presentation_definition":{ + "presentationDefinition":{ } } """; diff --git a/spi/identity-hub-spi/src/main/java/org/eclipse/edc/identityhub/spi/model/PresentationQuery.java b/spi/identity-hub-spi/src/main/java/org/eclipse/edc/identityhub/spi/model/PresentationQuery.java index c5bbf1af0..5d05fd703 100644 --- a/spi/identity-hub-spi/src/main/java/org/eclipse/edc/identityhub/spi/model/PresentationQuery.java +++ b/spi/identity-hub-spi/src/main/java/org/eclipse/edc/identityhub/spi/model/PresentationQuery.java @@ -29,7 +29,7 @@ */ public class PresentationQuery { public static final String PRESENTATION_QUERY_SCOPE_PROPERTY = IATP_PREFIX + "scope"; - public static final String PRESENTATION_QUERY_DEFINITION_PROPERTY = IATP_PREFIX + "presentation_definition"; + public static final String PRESENTATION_QUERY_DEFINITION_PROPERTY = IATP_PREFIX + "presentationDefinition"; public static final String PRESENTATION_QUERY_TYPE_PROPERTY = IATP_PREFIX + "Query"; private List scopes = new ArrayList<>(); private PresentationDefinition presentationDefinition;