diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java index 2eb643c..b7d29fa 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java @@ -5,8 +5,8 @@ import static org.oneedtech.inspect.core.probe.RunContext.Key.*; import static org.oneedtech.inspect.core.report.ReportUtil.onProbeException; import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT; -import static org.oneedtech.inspect.vc.Credential.CREDENTIAL_KEY; -import static org.oneedtech.inspect.vc.Credential.ProofType.EXTERNAL; +import static org.oneedtech.inspect.vc.AbstractBaseCredential.CREDENTIAL_KEY; +import static org.oneedtech.inspect.vc.VerifiableCredential.ProofType.EXTERNAL; import java.net.URI; import java.util.ArrayList; @@ -25,7 +25,7 @@ import org.oneedtech.inspect.util.json.ObjectMapperCache; import org.oneedtech.inspect.util.resource.Resource; import org.oneedtech.inspect.util.resource.UriResource; import org.oneedtech.inspect.util.resource.context.ResourceContext; -import org.oneedtech.inspect.vc.Credential.Type; +import org.oneedtech.inspect.vc.VerifiableCredential.Type; import org.oneedtech.inspect.vc.probe.ContextPropertyProbe; import org.oneedtech.inspect.vc.probe.EmbeddedProofProbe; import org.oneedtech.inspect.vc.probe.ExpirationProbe; @@ -39,32 +39,32 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; /** - * An inspector for EndorsementCredential objects. + * An inspector for EndorsementCredential objects. * @author mgylling */ public class EndorsementInspector extends VCInspector implements SubInspector { protected > EndorsementInspector(B builder) { super(builder); - } + } @Override public Report run(Resource resource, Map parentObjects) { - + /* * The resource param is the top-level credential that embeds the endorsement, we * expect parentObjects to provide a pointer to the JsonNode we should check. - * + * * The parent inspector is responsible to decode away possible jwt-ness, so that - * what we get here is a verbatim json node. - * + * what we get here is a verbatim json node. + * */ - - Credential endorsement = (Credential) checkNotNull(parentObjects.get(CREDENTIAL_KEY)); - + + VerifiableCredential endorsement = (VerifiableCredential) checkNotNull(parentObjects.get(CREDENTIAL_KEY)); + ObjectMapper mapper = ObjectMapperCache.get(DEFAULT); JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper); - + RunContext ctx = new RunContext.Builder() .put(this) .put(JACKSON_OBJECTMAPPER, mapper) @@ -74,18 +74,18 @@ public class EndorsementInspector extends VCInspector implements SubInspector { List accumulator = new ArrayList<>(); int probeCount = 0; try { - + //context and type properties - Credential.Type type = Type.EndorsementCredential; - for(Probe probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) { + VerifiableCredential.Type type = Type.EndorsementCredential; + for(Probe probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) { probeCount++; accumulator.add(probe.run(endorsement.getJson(), ctx)); if(broken(accumulator)) return abort(ctx, accumulator, probeCount); } - + //inline schema (parent inspector has already validated against canonical) accumulator.add(new InlineJsonSchemaProbe().run(endorsement.getJson(), ctx)); - + //signatures, proofs probeCount++; if(endorsement.getProofType() == EXTERNAL){ @@ -93,16 +93,16 @@ public class EndorsementInspector extends VCInspector implements SubInspector { accumulator.add(new ExternalProofProbe().run(endorsement, ctx)); } else { //The credential not contained in a jwt, must have an internal proof. - accumulator.add(new EmbeddedProofProbe().run(endorsement, ctx)); - + accumulator.add(new EmbeddedProofProbe().run(endorsement, ctx)); + } if(broken(accumulator)) return abort(ctx, accumulator, probeCount); //check refresh service if we are not already refreshed (check just like in external CLR) probeCount++; if(resource.getContext().get(REFRESHED) != TRUE) { - Optional newID = checkRefreshService(endorsement, ctx); - if(newID.isPresent()) { + Optional newID = checkRefreshService(endorsement, ctx); + if(newID.isPresent()) { //TODO resource.type return this.run( new UriResource(new URI(newID.get())) @@ -111,8 +111,8 @@ public class EndorsementInspector extends VCInspector implements SubInspector { } //revocation, expiration and issuance - for(Probe probe : List.of(new RevocationListProbe(), - new ExpirationProbe(), new IssuanceProbe())) { + for(Probe probe : List.of(new RevocationListProbe(), + new ExpirationProbe(), new IssuanceProbe())) { probeCount++; accumulator.add(probe.run(endorsement, ctx)); if(broken(accumulator)) return abort(ctx, accumulator, probeCount); @@ -129,7 +129,7 @@ public class EndorsementInspector extends VCInspector implements SubInspector { public Report run(R resource) { throw new IllegalStateException("must use #run(resource, map)"); } - + public static class Builder extends VCInspector.Builder { @SuppressWarnings("unchecked") @Override @@ -137,5 +137,5 @@ public class EndorsementInspector extends VCInspector implements SubInspector { return new EndorsementInspector(this); } } - + } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java index c90a864..e60b8e2 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java @@ -6,7 +6,7 @@ import static org.oneedtech.inspect.core.report.ReportUtil.onProbeException; import static org.oneedtech.inspect.util.code.Defensives.*; import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT; import static org.oneedtech.inspect.vc.AbstractBaseCredential.CREDENTIAL_KEY; -import static org.oneedtech.inspect.vc.Credential.ProofType.EXTERNAL; +import static org.oneedtech.inspect.vc.VerifiableCredential.ProofType.EXTERNAL; import static org.oneedtech.inspect.vc.payload.PayloadParser.fromJwt; import static org.oneedtech.inspect.vc.util.JsonNodeUtil.asNodeList; @@ -34,7 +34,7 @@ import org.oneedtech.inspect.util.resource.ResourceType; import org.oneedtech.inspect.util.resource.UriResource; import org.oneedtech.inspect.util.resource.context.ResourceContext; import org.oneedtech.inspect.util.spec.Specification; -import org.oneedtech.inspect.vc.Credential.Type; +import org.oneedtech.inspect.vc.VerifiableCredential.Type; import org.oneedtech.inspect.vc.payload.PngParser; import org.oneedtech.inspect.vc.payload.SvgParser; import org.oneedtech.inspect.vc.probe.ContextPropertyProbe; @@ -58,7 +58,7 @@ import com.google.common.collect.ImmutableList; * @author mgylling */ public class OB30Inspector extends VCInspector implements SubInspector { - protected final List> userProbes; + protected final List> userProbes; protected OB30Inspector(OB30Inspector.Builder builder) { super(builder); @@ -93,7 +93,7 @@ public class OB30Inspector extends VCInspector implements SubInspector { .put(resource) .put(Key.JACKSON_OBJECTMAPPER, mapper) .put(Key.JSONPATH_EVALUATOR, jsonPath) - .put(Key.GENERATED_OBJECT_BUILDER, new Credential.Builder()) + .put(Key.GENERATED_OBJECT_BUILDER, new VerifiableCredential.Builder()) .put(Key.PNG_CREDENTIAL_KEY, PngParser.Keys.OB30) .put(Key.SVG_CREDENTIAL_QNAME, SvgParser.QNames.OB30) .build(); @@ -108,15 +108,15 @@ public class OB30Inspector extends VCInspector implements SubInspector { if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount); //we expect the above to place a generated object in the context - Credential ob = ctx.getGeneratedObject(Credential.ID); + VerifiableCredential ob = ctx.getGeneratedObject(VerifiableCredential.ID); //call the subinspector method of this - Report subReport = this.run(resource, Map.of(Credential.CREDENTIAL_KEY, ob)); + Report subReport = this.run(resource, Map.of(VerifiableCredential.CREDENTIAL_KEY, ob)); probeCount += subReport.getSummary().getTotalRun(); accumulator.add(subReport); //finally, run any user-added probes - for(Probe probe : userProbes) { + for(Probe probe : userProbes) { probeCount++; accumulator.add(probe.run(ob, ctx)); } @@ -131,11 +131,11 @@ public class OB30Inspector extends VCInspector implements SubInspector { @Override public Report run(Resource resource, Map parentObjects) { - Credential ob = checkNotNull((Credential)parentObjects.get(CREDENTIAL_KEY)); + VerifiableCredential ob = checkNotNull((VerifiableCredential)parentObjects.get(CREDENTIAL_KEY)); ObjectMapper mapper = ObjectMapperCache.get(DEFAULT); JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper); - Credential.Builder credentialBuilder = new Credential.Builder(); + VerifiableCredential.Builder credentialBuilder = new VerifiableCredential.Builder(); RunContext ctx = new RunContext.Builder() .put(this) .put(resource) @@ -152,7 +152,7 @@ public class OB30Inspector extends VCInspector implements SubInspector { try { //context and type properties - Credential.Type type = Type.OpenBadgeCredential; + VerifiableCredential.Type type = Type.OpenBadgeCredential; for(Probe probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) { probeCount++; accumulator.add(probe.run(ob.getJson(), ctx)); @@ -194,7 +194,7 @@ public class OB30Inspector extends VCInspector implements SubInspector { } //revocation, expiration and issuance - for(Probe probe : List.of(new RevocationListProbe(), + for(Probe probe : List.of(new RevocationListProbe(), new ExpirationProbe(), new IssuanceProbe())) { probeCount++; accumulator.add(probe.run(ob, ctx)); @@ -207,7 +207,7 @@ public class OB30Inspector extends VCInspector implements SubInspector { List endorsements = asNodeList(ob.getJson(), "$..endorsement", jsonPath); for(JsonNode node : endorsements) { probeCount++; - Credential endorsement = credentialBuilder.resource(resource).jsonData(node).build(); + VerifiableCredential endorsement = credentialBuilder.resource(resource).jsonData(node).build(); accumulator.add(endorsementInspector.run(resource, Map.of(CREDENTIAL_KEY, endorsement))); } @@ -217,7 +217,7 @@ public class OB30Inspector extends VCInspector implements SubInspector { probeCount++; String jwt = node.asText(); JsonNode vcNode = fromJwt(jwt, ctx); - Credential endorsement = credentialBuilder.resource(resource).jsonData(node).jwt(jwt).build(); + VerifiableCredential endorsement = credentialBuilder.resource(resource).jsonData(node).jwt(jwt).build(); accumulator.add(endorsementInspector.run(resource, Map.of(CREDENTIAL_KEY, endorsement))); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/VCInspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/VCInspector.java index a4a90dc..19a89bc 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/VCInspector.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/VCInspector.java @@ -18,19 +18,19 @@ import com.fasterxml.jackson.databind.JsonNode; * @author mgylling */ public abstract class VCInspector extends Inspector { - + protected > VCInspector(B builder) { - super(builder); + super(builder); } - + protected Report abort(RunContext ctx, List accumulator, int probeCount) { return new Report(ctx, new ReportItems(accumulator), probeCount); } - + protected boolean broken(List accumulator) { return broken(accumulator, false); } - + protected boolean broken(List accumulator, boolean force) { if(!force && getBehavior(Inspector.Behavior.VALIDATOR_FAIL_FAST) == Boolean.FALSE) { return false; @@ -40,15 +40,15 @@ public abstract class VCInspector extends Inspector { } return false; } - + /** - * If the AchievementCredential or EndorsementCredential has a “refreshService” property and the type of the - * RefreshService object is “1EdTechCredentialRefresh”, you should fetch the refreshed credential from the URL - * provided, then start the verification process over using the response as input. If the request fails, + * If the AchievementCredential or EndorsementCredential has a “refreshService” property and the type of the + * RefreshService object is “1EdTechCredentialRefresh”, you should fetch the refreshed credential from the URL + * provided, then start the verification process over using the response as input. If the request fails, * the credential is invalid. */ - protected Optional checkRefreshService(Credential crd, RunContext ctx) { - JsonNode refreshServiceNode = crd.getJson().get("refreshService"); + protected Optional checkRefreshService(VerifiableCredential crd, RunContext ctx) { + JsonNode refreshServiceNode = crd.getJson().get("refreshService"); if(refreshServiceNode != null) { JsonNode serviceTypeNode = refreshServiceNode.get("type"); if(serviceTypeNode != null && serviceTypeNode.asText().equals("1EdTechCredentialRefresh")) { @@ -56,22 +56,22 @@ public abstract class VCInspector extends Inspector { if(serviceURINode != null) { return Optional.of(serviceURINode.asText()); } - } - } + } + } return Optional.empty(); } protected static final String REFRESHED = "is.refreshed.credential"; - + public abstract static class Builder> extends Inspector.Builder { - final List> probes; + final List> probes; public Builder() { super(); this.probes = new ArrayList<>(); } - - public VCInspector.Builder add(Probe probe) { + + public VCInspector.Builder add(Probe probe) { probes.add(probe); return this; } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/Credential.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/VerifiableCredential.java similarity index 71% rename from inspector-vc/src/main/java/org/oneedtech/inspect/vc/Credential.java rename to inspector-vc/src/main/java/org/oneedtech/inspect/vc/VerifiableCredential.java index ecd1722..7daf258 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/Credential.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/VerifiableCredential.java @@ -1,9 +1,9 @@ package org.oneedtech.inspect.vc; -import static org.oneedtech.inspect.vc.Credential.Type.AchievementCredential; -import static org.oneedtech.inspect.vc.Credential.Type.ClrCredential; -import static org.oneedtech.inspect.vc.Credential.Type.EndorsementCredential; -import static org.oneedtech.inspect.vc.Credential.Type.VerifiablePresentation; +import static org.oneedtech.inspect.vc.VerifiableCredential.Type.AchievementCredential; +import static org.oneedtech.inspect.vc.VerifiableCredential.Type.ClrCredential; +import static org.oneedtech.inspect.vc.VerifiableCredential.Type.EndorsementCredential; +import static org.oneedtech.inspect.vc.VerifiableCredential.Type.VerifiablePresentation; import java.util.Iterator; import java.util.Map; @@ -23,14 +23,14 @@ import com.google.common.collect.ImmutableMap; * and the extracted JSON data plus any other stuff Probes need. * @author mgylling */ -public class Credential extends AbstractBaseCredential { - final Credential.Type credentialType; +public class VerifiableCredential extends AbstractBaseCredential { + final VerifiableCredential.Type credentialType; - protected Credential(Resource resource, JsonNode data, String jwt, Map schemas) { + protected VerifiableCredential(Resource resource, JsonNode data, String jwt, Map schemas) { super(ID, resource, data, jwt, schemas); ArrayNode typeNode = (ArrayNode)jsonData.get("type"); - this.credentialType = Credential.Type.valueOf(typeNode); + this.credentialType = VerifiableCredential.Type.valueOf(typeNode); } public String getCredentialType() { @@ -41,7 +41,7 @@ public class Credential extends AbstractBaseCredential { return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL; } - private static final Map schemas = new ImmutableMap.Builder() + private static final Map schemas = new ImmutableMap.Builder() .put(AchievementCredential, Catalog.OB_30_ACHIEVEMENTCREDENTIAL_JSON) .put(ClrCredential, Catalog.CLR_20_CLRCREDENTIAL_JSON) .put(VerifiablePresentation, Catalog.CLR_20_CLRCREDENTIAL_JSON) @@ -58,7 +58,7 @@ public class Credential extends AbstractBaseCredential { VerifiableCredential, //this is an underspecifier in our context Unknown; - public static Credential.Type valueOf (ArrayNode typeArray) { + public static VerifiableCredential.Type valueOf (ArrayNode typeArray) { if(typeArray != null) { Iterator iter = typeArray.iterator(); while(iter.hasNext()) { @@ -91,18 +91,18 @@ public class Credential extends AbstractBaseCredential { .toString(); } - public static class Builder extends AbstractBaseCredential.Builder { + public static class Builder extends AbstractBaseCredential.Builder { @Override - public Credential build() { + public VerifiableCredential build() { // transform key of schemas map to string because the type of the key in the base map is generic // and our specific key is an Enum - return new Credential(getResource(), getJsonData(), getJwt(), + return new VerifiableCredential(getResource(), getJsonData(), getJwt(), schemas.entrySet().stream().collect(Collectors.toMap( entry -> entry.getKey().toString(), entry -> entry.getValue()))); } } - public static final String ID = Credential.class.getCanonicalName(); + public static final String ID = VerifiableCredential.class.getCanonicalName(); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/PayloadParser.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/PayloadParser.java index 8a18c88..dc9307f 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/PayloadParser.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/PayloadParser.java @@ -8,7 +8,7 @@ import org.oneedtech.inspect.core.probe.RunContext; import org.oneedtech.inspect.util.resource.Resource; import org.oneedtech.inspect.util.resource.ResourceType; import org.oneedtech.inspect.vc.AbstractBaseCredential; -import org.oneedtech.inspect.vc.Credential; +import org.oneedtech.inspect.vc.VerifiableCredential; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ContextPropertyProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ContextPropertyProbe.java index 87a1999..d3fd35d 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ContextPropertyProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ContextPropertyProbe.java @@ -1,6 +1,6 @@ package org.oneedtech.inspect.vc.probe; -import static org.oneedtech.inspect.vc.Credential.Type.*; +import static org.oneedtech.inspect.vc.VerifiableCredential.Type.*; import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; @@ -11,7 +11,7 @@ import java.util.Set; 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.VerifiableCredential; import org.oneedtech.inspect.vc.util.JsonNodeUtil; @@ -21,13 +21,13 @@ import com.google.common.collect.ImmutableMap; /** * A Probe that verifies a credential's context property. - * + * * @author mgylling */ public class ContextPropertyProbe extends Probe { - private final Credential.Type type; + private final VerifiableCredential.Type type; - public ContextPropertyProbe(Credential.Type type) { + public ContextPropertyProbe(VerifiableCredential.Type type) { super(ID); this.type = checkNotNull(type); } @@ -45,7 +45,7 @@ public class ContextPropertyProbe extends Probe { .filter(s->s.contains(type)) .findFirst() .orElseThrow(()-> new IllegalArgumentException(type.name() + " not recognized"))); - + List given = JsonNodeUtil.asStringList(contextNode); int pos = 0; for (String uri : expected) { @@ -58,7 +58,7 @@ public class ContextPropertyProbe extends Probe { return success(ctx); } - private final static Map, List> values = new ImmutableMap.Builder, List>() + private final static Map, List> values = new ImmutableMap.Builder, List>() .put(Set.of(OpenBadgeCredential, AchievementCredential, EndorsementCredential), List.of("https://www.w3.org/2018/credentials/v1", //"https://purl.imsglobal.org/spec/ob/v3p0/context.json")) //dev legacy @@ -69,7 +69,7 @@ public class ContextPropertyProbe extends Probe { // "https://purl.imsglobal.org/spec/ob/v3p0/context.json")) //dev legacy "https://purl.imsglobal.org/spec/clr/v2p0/context.json", "https://purl.imsglobal.org/spec/ob/v3p0/context.json")) - + .build(); public static final String ID = ContextPropertyProbe.class.getSimpleName(); diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/CredentialParseProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/CredentialParseProbe.java index 3827e90..93cc98d 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/CredentialParseProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/CredentialParseProbe.java @@ -9,7 +9,7 @@ import org.oneedtech.inspect.util.resource.Resource; import org.oneedtech.inspect.util.resource.ResourceType; import org.oneedtech.inspect.util.resource.detect.TypeDetector; import org.oneedtech.inspect.vc.AbstractBaseCredential; -import org.oneedtech.inspect.vc.Credential; +import org.oneedtech.inspect.vc.VerifiableCredential; import org.oneedtech.inspect.vc.payload.PayloadParserFactory; /** @@ -39,7 +39,7 @@ public class CredentialParseProbe extends Probe { } } - if(!Credential.RECOGNIZED_PAYLOAD_TYPES.contains(type.get())) { + if(!VerifiableCredential.RECOGNIZED_PAYLOAD_TYPES.contains(type.get())) { return fatal("Payload type not supported: " + type.get().getName(), context); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EmbeddedProofProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EmbeddedProofProbe.java index b3fe3b4..b985fee 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EmbeddedProofProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EmbeddedProofProbe.java @@ -7,7 +7,7 @@ import java.util.Optional; 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.VerifiableCredential; import com.apicatalog.jsonld.StringUtils; import com.apicatalog.jsonld.document.Document; @@ -15,7 +15,6 @@ import com.apicatalog.jsonld.loader.DocumentLoaderOptions; import com.apicatalog.multibase.Multibase; import com.apicatalog.multicodec.Multicodec; import com.apicatalog.multicodec.Multicodec.Codec; -import com.danubetech.verifiablecredentials.VerifiableCredential; import foundation.identity.jsonld.ConfigurableDocumentLoader; import info.weboftrust.ldsignatures.LdProof; @@ -28,7 +27,7 @@ import jakarta.json.JsonStructure; * * @author mgylling */ -public class EmbeddedProofProbe extends Probe { +public class EmbeddedProofProbe extends Probe { public EmbeddedProofProbe() { super(ID); @@ -39,11 +38,11 @@ public class EmbeddedProofProbe extends Probe { * (https://github.com/danubetech/verifiable-credentials-java) */ @Override - public ReportItems run(Credential crd, RunContext ctx) throws Exception { + public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception { // TODO: What there are multiple proofs? - VerifiableCredential vc = VerifiableCredential.fromJson(new StringReader(crd.getJson().toString())); + com.danubetech.verifiablecredentials.VerifiableCredential vc = com.danubetech.verifiablecredentials.VerifiableCredential.fromJson(new StringReader(crd.getJson().toString())); ConfigurableDocumentLoader documentLoader = new ConfigurableDocumentLoader(); documentLoader.setEnableHttp(true); documentLoader.setEnableHttps(true); @@ -97,7 +96,7 @@ public class EmbeddedProofProbe extends Probe { if (keyStructure.isEmpty()) { return error("Key document not found at " + method, ctx); } - + // First look for a Ed25519VerificationKey2020 document controller = keyStructure.get().asJsonObject().getString("controller"); if (StringUtils.isBlank(controller)) { @@ -113,7 +112,7 @@ public class EmbeddedProofProbe extends Probe { } else { publicKeyMultibase = keyStructure.get().asJsonObject().getString("publicKeyMultibase"); } - + } catch (Exception e) { return error("Invalid verification key URL: " + e.getMessage(), ctx); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExpirationProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExpirationProbe.java index fcebd0c..0c9092c 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExpirationProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExpirationProbe.java @@ -5,39 +5,39 @@ import java.time.ZonedDateTime; 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.VerifiableCredential; import com.fasterxml.jackson.databind.JsonNode; /** - * A Probe that verifies a credential's expiration status + * A Probe that verifies a credential's expiration status * @author mgylling */ -public class ExpirationProbe extends Probe { - +public class ExpirationProbe extends Probe { + public ExpirationProbe() { super(ID); } - + @Override - public ReportItems run(Credential crd, RunContext ctx) throws Exception { - /* - * If the AchievementCredential or EndorsementCredential has an “expirationDate” property - * and the expiration date is prior to the current date, the credential has expired. - */ + public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception { + /* + * If the AchievementCredential or EndorsementCredential has an “expirationDate” property + * and the expiration date is prior to the current date, the credential has expired. + */ JsonNode node = crd.getJson().get("expirationDate"); if(node != null) { try { ZonedDateTime expirationDate = ZonedDateTime.parse(node.textValue()); if (ZonedDateTime.now().isAfter(expirationDate)) { return fatal("The credential has expired (expiration date was " + node.asText() + ").", ctx); - } + } } catch (Exception e) { - return exception("Error while checking expirationDate: " + e.getMessage(), ctx.getResource()); + return exception("Error while checking expirationDate: " + e.getMessage(), ctx.getResource()); } } return success(ctx); } - - public static final String ID = ExpirationProbe.class.getSimpleName(); + + public static final String ID = ExpirationProbe.class.getSimpleName(); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExternalProofProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExternalProofProbe.java index b4bccb0..b14ce3c 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExternalProofProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExternalProofProbe.java @@ -21,7 +21,7 @@ import org.apache.http.util.EntityUtils; 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.VerifiableCredential; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; @@ -36,32 +36,32 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Splitter; /** - * A Probe that verifies credential external proof (jwt) + * A Probe that verifies credential external proof (jwt) * @author mlyon */ -public class ExternalProofProbe extends Probe { - +public class ExternalProofProbe extends Probe { + public ExternalProofProbe() { super(ID); } - + @Override - public ReportItems run(Credential crd, RunContext ctx) throws Exception { + public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception { try { verifySignature(crd, ctx); } catch (Exception e) { return fatal("Error verifying jwt signature: " + e.getMessage(), ctx); - } + } return success(ctx); } - private void verifySignature(Credential crd, RunContext ctx) throws Exception { + private void verifySignature(VerifiableCredential crd, RunContext ctx) throws Exception { checkTrue(crd.getJwt().isPresent(), "no jwt supplied"); checkTrue(crd.getJwt().get().length() > 0, "no jwt supplied"); - + DecodedJWT decodedJwt = null; String jwt = crd.getJwt().get(); - + List parts = Splitter.on('.').splitToList(jwt); if(parts.size() != 3) throw new IllegalArgumentException("invalid jwt"); @@ -85,7 +85,7 @@ public class ExternalProofProbe extends Probe { if(jwk == null && kid == null) { throw new Exception("Key must present in either jwk or kid value."); } if(kid != null){ - //Load jwk JsonNode from url and do the rest the same below. + //Load jwk JsonNode from url and do the rest the same below. //TODO Consider additional testing. String kidUrl = kid.textValue(); String jwkResponse = fetchJwk(kidUrl); @@ -145,7 +145,7 @@ public class ExternalProofProbe extends Probe { return responseString; } - + public static final String ID = ExternalProofProbe.class.getSimpleName(); } \ No newline at end of file diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/InlineJsonSchemaProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/InlineJsonSchemaProbe.java index 7f3f86e..30c4324 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/InlineJsonSchemaProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/InlineJsonSchemaProbe.java @@ -11,64 +11,64 @@ import org.oneedtech.inspect.core.probe.RunContext; import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe; import org.oneedtech.inspect.core.report.ReportItems; import org.oneedtech.inspect.schema.SchemaKey; -import org.oneedtech.inspect.vc.Credential; +import org.oneedtech.inspect.vc.VerifiableCredential; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; /** - * Detect inline schemas in a credential and run them. + * Detect inline schemas in a credential and run them. * @author mgylling */ public class InlineJsonSchemaProbe extends Probe { private static final Set types = Set.of("1EdTechJsonSchemaValidator2019"); private SchemaKey skip; - + public InlineJsonSchemaProbe() { super(ID); } - + public InlineJsonSchemaProbe(SchemaKey skip) { super(ID); this.skip = skip; } - + @Override public ReportItems run(JsonNode root, RunContext ctx) throws Exception { List accumulator = new ArrayList<>(); - Set ioErrors = new HashSet<>(); + Set ioErrors = new HashSet<>(); - //note - we don't get deep nested ones in e.g. EndorsementCredential + //note - we don't get deep nested ones in e.g. EndorsementCredential JsonNode credentialSchemaNode = root.get("credentialSchema"); if(credentialSchemaNode == null) return success(ctx); - + ArrayNode schemas = (ArrayNode) credentialSchemaNode; //TODO guard this cast - + for(JsonNode schemaNode : schemas) { JsonNode typeNode = schemaNode.get("type"); - if(typeNode == null || !types.contains(typeNode.asText())) continue; - JsonNode idNode = schemaNode.get("id"); + if(typeNode == null || !types.contains(typeNode.asText())) continue; + JsonNode idNode = schemaNode.get("id"); if(idNode == null) continue; - String id = idNode.asText().strip(); - if(ioErrors.contains(id)) continue; - if(equals(skip, id)) continue; - try { + String id = idNode.asText().strip(); + if(ioErrors.contains(id)) continue; + if(equals(skip, id)) continue; + try { accumulator.add(new JsonSchemaProbe(id).run(root, ctx)); - } catch (Exception e) { + } catch (Exception e) { if(!ioErrors.contains(id)) { ioErrors.add(id); accumulator.add(error("Could not read schema resource " + id, ctx)); - } - } + } + } } - + return new ReportItems(accumulator); } - + private boolean equals(SchemaKey key, String id) { if(key == null) return false; - return key.getCanonicalURI().equals(id); + return key.getCanonicalURI().equals(id); } - + public static final String ID = InlineJsonSchemaProbe.class.getSimpleName(); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/IssuanceProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/IssuanceProbe.java index 04c5d6b..7b693ff 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/IssuanceProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/IssuanceProbe.java @@ -5,39 +5,39 @@ import java.time.ZonedDateTime; 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.VerifiableCredential; import com.fasterxml.jackson.databind.JsonNode; /** - * A Probe that verifies a credential's issuance status + * A Probe that verifies a credential's issuance status * @author mgylling */ -public class IssuanceProbe extends Probe { - +public class IssuanceProbe extends Probe { + public IssuanceProbe() { super(ID); } - + @Override - public ReportItems run(Credential crd, RunContext ctx) throws Exception { - /* - * If the AchievementCredential or EndorsementCredential “issuanceDate” + public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception { + /* + * If the AchievementCredential or EndorsementCredential “issuanceDate” * property after the current date, the credential is not yet valid. */ - JsonNode node = crd.getJson().get("issuanceDate"); + JsonNode node = crd.getJson().get("issuanceDate"); if(node != null) { try { - ZonedDateTime issuanceDate = ZonedDateTime.parse(node.textValue()); + ZonedDateTime issuanceDate = ZonedDateTime.parse(node.textValue()); if (issuanceDate.isAfter(ZonedDateTime.now())) { return fatal("The credential is not yet issued (issuance date is " + node.asText() + ").", ctx); - } + } } catch (Exception e) { return exception("Error while checking issuanceDate: " + e.getMessage(), ctx.getResource()); } } return success(ctx); - } - - public static final String ID = IssuanceProbe.class.getSimpleName(); + } + + public static final String ID = IssuanceProbe.class.getSimpleName(); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/RevocationListProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/RevocationListProbe.java index ca11b0f..576c6e4 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/RevocationListProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/RevocationListProbe.java @@ -10,7 +10,7 @@ import java.util.List; 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.VerifiableCredential; import org.oneedtech.inspect.vc.util.JsonNodeUtil; import com.fasterxml.jackson.databind.JsonNode; @@ -20,24 +20,24 @@ import com.fasterxml.jackson.databind.ObjectMapper; * A Probe that verifies a credential's revocation status. * @author mgylling */ -public class RevocationListProbe extends Probe { - +public class RevocationListProbe extends Probe { + public RevocationListProbe() { super(ID); } - + @Override - public ReportItems run(Credential crd, RunContext ctx) throws Exception { + public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception { /* - * If the AchievementCredential or EndorsementCredential has a “credentialStatus” property - * and the type of the CredentialStatus object is “1EdTechRevocationList”, fetch the - * credential status from the URL provided. If the request is unsuccessful, - * report a warning, not an error. + * If the AchievementCredential or EndorsementCredential has a “credentialStatus” property + * and the type of the CredentialStatus object is “1EdTechRevocationList”, fetch the + * credential status from the URL provided. If the request is unsuccessful, + * report a warning, not an error. */ - + JsonNode credentialStatus = crd.getJson().get("credentialStatus"); - if(credentialStatus != null) { + if(credentialStatus != null) { JsonNode type = credentialStatus.get("type"); if(type != null && type.asText().strip().equals("1EdTechRevocationList")) { JsonNode listID = credentialStatus.get("id"); @@ -46,34 +46,34 @@ public class RevocationListProbe extends Probe { URL url = new URI(listID.asText().strip()).toURL(); try (InputStream is = url.openStream()) { JsonNode revocList = ((ObjectMapper)ctx.get(JACKSON_OBJECTMAPPER)).readTree(is.readAllBytes()); - - /* To check if a credential has been revoked, the verifier issues a GET request - * to the URL of the issuer's 1EdTech Revocation List Status Method. If the - * credential's id is in the list of revokedCredentials and the value of + + /* To check if a credential has been revoked, the verifier issues a GET request + * to the URL of the issuer's 1EdTech Revocation List Status Method. If the + * credential's id is in the list of revokedCredentials and the value of * revoked is true or ommitted, the issuer has revoked the credential. */ - + JsonNode crdID = crd.getJson().get("id"); //TODO these != checks sb removed (trigger warning) if(crdID != null) { List list = JsonNodeUtil.asNodeList(revocList.get("revokedCredentials")); if(list != null) { for(JsonNode item : list) { JsonNode revID = item.get("id"); - JsonNode revoked = item.get("revoked"); + JsonNode revoked = item.get("revoked"); if(revID != null && revID.equals(crdID) && (revoked == null || revoked.asBoolean())) { - return fatal("Credential has been revoked", ctx); + return fatal("Credential has been revoked", ctx); } - } - } + } + } } - } + } } catch (Exception e) { return warning("Error when fetching credentialStatus resource " + e.getMessage(), ctx); - } - } - } + } + } + } } return success(ctx); - } - - public static final String ID = RevocationListProbe.class.getSimpleName(); + } + + public static final String ID = RevocationListProbe.class.getSimpleName(); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java index 804380e..ed67b8b 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java @@ -7,8 +7,8 @@ import java.util.List; 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.Credential.Type; +import org.oneedtech.inspect.vc.VerifiableCredential; +import org.oneedtech.inspect.vc.VerifiableCredential.Type; import org.oneedtech.inspect.vc.util.JsonNodeUtil; import com.fasterxml.jackson.databind.JsonNode; @@ -16,13 +16,13 @@ import com.fasterxml.jackson.databind.node.ArrayNode; /** * A Probe that verifies a credential's type property. - * + * * @author mgylling */ public class TypePropertyProbe extends Probe { - private final Credential.Type expected; + private final VerifiableCredential.Type expected; - public TypePropertyProbe(Credential.Type expected) { + public TypePropertyProbe(VerifiableCredential.Type expected) { super(ID); this.expected = checkNotNull(expected); } @@ -40,15 +40,15 @@ public class TypePropertyProbe extends Probe { return fatal("The type property does not contain the entry 'VerifiableCredential'", ctx); } - if (expected == Credential.Type.OpenBadgeCredential) { + if (expected == VerifiableCredential.Type.OpenBadgeCredential) { if (!values.contains("OpenBadgeCredential") && !values.contains("AchievementCredential")) { return fatal("The type property does not contain one of 'OpenBadgeCredential' or 'AchievementCredential'", ctx); } - } else if (expected == Credential.Type.ClrCredential) { + } else if (expected == VerifiableCredential.Type.ClrCredential) { if (!values.contains("ClrCredential")) { return fatal("The type property does not contain the entry 'ClrCredential'", ctx); } - } else if (expected == Credential.Type.EndorsementCredential) { + } else if (expected == VerifiableCredential.Type.EndorsementCredential) { if (!values.contains("EndorsementCredential")) { return fatal("The type property does not contain the entry 'EndorsementCredential'", ctx); }