diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/JsonLdGeneratedObject.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/JsonLdGeneratedObject.java new file mode 100644 index 0000000..5a529bd --- /dev/null +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/JsonLdGeneratedObject.java @@ -0,0 +1,18 @@ +package org.oneedtech.inspect.vc; + +import org.oneedtech.inspect.core.probe.GeneratedObject; + +public class JsonLdGeneratedObject extends GeneratedObject { + private String json; + + public JsonLdGeneratedObject(String json) { + super(ID, GeneratedObject.Type.INTERNAL); + this.json = json; + } + + public String getJson() { + return json; + } + + public static final String ID = JsonLdGeneratedObject.class.getCanonicalName(); +} diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB20Inspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB20Inspector.java index c487768..dd1f6b7 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB20Inspector.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB20Inspector.java @@ -25,6 +25,7 @@ import org.oneedtech.inspect.vc.payload.PngParser; import org.oneedtech.inspect.vc.payload.SvgParser; import org.oneedtech.inspect.vc.probe.CredentialParseProbe; import org.oneedtech.inspect.vc.probe.JsonLDCompactionProve; +import org.oneedtech.inspect.vc.probe.JsonLDValidationProbe; import org.oneedtech.inspect.vc.util.CachingDocumentLoader; import com.fasterxml.jackson.databind.ObjectMapper; @@ -84,19 +85,30 @@ public class OB20Inspector extends Inspector { int probeCount = 0; try { - //detect type (png, svg, json, jwt) and extract json data - probeCount++; - accumulator.add(new CredentialParseProbe().run(resource, ctx)); - if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount); + //detect type (png, svg, json, jwt) and extract json data + probeCount++; + accumulator.add(new CredentialParseProbe().run(resource, ctx)); + if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount); - // //we expect the above to place a generated object in the context - Assertion assertion = ctx.getGeneratedObject(Assertion.ID); + // we expect the above to place a generated object in the context + Assertion assertion = ctx.getGeneratedObject(Assertion.ID); - // let's compact and validate - accumulator.add(getCompactionProbe(assertion).run(assertion, ctx)); - if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount); + // let's compact + accumulator.add(getCompactionProbe(assertion).run(assertion, ctx)); + if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount); + // validate JSON LD + JsonLdGeneratedObject jsonLdGeneratedObject = ctx.getGeneratedObject(JsonLdGeneratedObject.ID); + accumulator.add(new JsonLDValidationProbe(jsonLdGeneratedObject).run(assertion, ctx)); + if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount); + //canonical schema and inline schemata + // SchemaKey schema = assertion.getSchemaKey().orElseThrow(); + // for(Probe probe : List.of(new JsonSchemaProbe(schema), new InlineJsonSchemaProbe(schema))) { + // probeCount++; + // accumulator.add(probe.run(assertion.getJson(), ctx)); + // if(broken(accumulator)) return abort(ctx, accumulator, probeCount); + // } } catch (Exception e) { accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e)); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDCompactionProve.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDCompactionProve.java index 3cabea1..e849395 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDCompactionProve.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDCompactionProve.java @@ -8,6 +8,7 @@ import org.oneedtech.inspect.core.probe.Probe; import org.oneedtech.inspect.core.probe.RunContext; import org.oneedtech.inspect.core.report.ReportItems; import org.oneedtech.inspect.vc.Credential; +import org.oneedtech.inspect.vc.JsonLdGeneratedObject; import org.oneedtech.inspect.vc.util.CachingDocumentLoader; import com.apicatalog.jsonld.JsonLd; @@ -39,13 +40,17 @@ public class JsonLDCompactionProve extends Probe { JsonDocument jsonDocument = JsonDocument.of(new StringReader(crd.getJson().toString())); CompactionApi compactApi = JsonLd.compact(jsonDocument, context); compactApi.options(new JsonLdOptions(new CachingDocumentLoader(localDomains))); + JsonObject compactedObject = compactApi.get(); + ctx.addGeneratedObject(new JsonLdGeneratedObject(compactedObject.toString())); // Handle mismatch between URL node source and declared ID. if (compactedObject.get("id") != null && crd.getResource().getID() != null && !compactedObject.get("id").toString().equals(crd.getResource().getID())) { + // TODO: a new fetch of the JSON document at id is required return warning("Node fetched from source " + crd.getResource().getID() + " declared its id as " + compactedObject.get("id").toString(), ctx); } + return success(this, ctx); } catch (Exception e) { return fatal("Error while parsing credential: " + e.getMessage(), ctx); diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDValidationProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDValidationProbe.java new file mode 100644 index 0000000..23bc2cd --- /dev/null +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonLDValidationProbe.java @@ -0,0 +1,33 @@ +package org.oneedtech.inspect.vc.probe; + +import java.io.StringReader; + +import org.oneedtech.inspect.core.probe.Probe; +import org.oneedtech.inspect.core.probe.RunContext; +import org.oneedtech.inspect.core.report.ReportItems; +import org.oneedtech.inspect.vc.Credential; +import org.oneedtech.inspect.vc.JsonLdGeneratedObject; + +import foundation.identity.jsonld.JsonLDObject; +import foundation.identity.jsonld.validation.Validation; + +public class JsonLDValidationProbe extends Probe { + private final JsonLdGeneratedObject jsonLdObject; + + public JsonLDValidationProbe(JsonLdGeneratedObject jsonLdObject) { + super(); + this.jsonLdObject = jsonLdObject; + } + + @Override + public ReportItems run(Credential crd, RunContext ctx) throws Exception { + JsonLDObject jsonLd = JsonLDObject.fromJson(new StringReader(jsonLdObject.getJson())); + try { + Validation.validate(jsonLd); + return success(this, ctx); + } catch (Exception e) { + return fatal("Error while validation JSON LD object: " + e.getMessage(), ctx); + } + } + +}